Browse Source

feat: replace window.prompt with showPrompt

Yidadaa 1 year ago
parent
commit
ea6926cad3

+ 5 - 4
app/components/button.module.scss

@@ -27,6 +27,11 @@
       fill: white !important;
     }
   }
+
+  &:hover,
+  &:focus {
+    border-color: var(--primary);
+  }
 }
 
 .shadow {
@@ -37,10 +42,6 @@
   border: var(--border-in-light);
 }
 
-.icon-button:hover {
-  border-color: var(--primary);
-}
-
 .icon-button-icon {
   width: 16px;
   height: 16px;

+ 4 - 0
app/components/button.tsx

@@ -12,6 +12,8 @@ export function IconButton(props: {
   className?: string;
   title?: string;
   disabled?: boolean;
+  tabIndex?: number;
+  autoFocus?: boolean;
 }) {
   return (
     <button
@@ -25,6 +27,8 @@ export function IconButton(props: {
       title={props.title}
       disabled={props.disabled}
       role="button"
+      tabIndex={props.tabIndex}
+      autoFocus={props.autoFocus}
     >
       {props.icon && (
         <div

+ 8 - 5
app/components/chat.tsx

@@ -61,7 +61,7 @@ import Locale from "../locales";
 import { IconButton } from "./button";
 import styles from "./chat.module.scss";
 
-import { ListItem, Modal, showConfirm, showToast } from "./ui-lib";
+import { ListItem, Modal, showConfirm, showPrompt, showToast } from "./ui-lib";
 import { useLocation, useNavigate } from "react-router-dom";
 import { LAST_INPUT_KEY, Path, REQUEST_TIMEOUT_MS } from "../constant";
 import { Avatar } from "./emoji";
@@ -778,10 +778,13 @@ export function Chat() {
   const [showPromptModal, setShowPromptModal] = useState(false);
 
   const renameSession = () => {
-    const newTopic = prompt(Locale.Chat.Rename, session.topic);
-    if (newTopic && newTopic !== session.topic) {
-      chatStore.updateCurrentSession((session) => (session.topic = newTopic!));
-    }
+    showPrompt(Locale.Chat.Rename, session.topic).then((newTopic) => {
+      if (newTopic && newTopic !== session.topic) {
+        chatStore.updateCurrentSession(
+          (session) => (session.topic = newTopic!),
+        );
+      }
+    });
   };
 
   const clientConfig = useMemo(() => getClientConfig(), []);

+ 20 - 0
app/components/ui-lib.module.scss

@@ -228,3 +228,23 @@
     pointer-events: none;
   }
 }
+
+.modal-input {
+  height: 100%;
+  width: 100%;
+  border-radius: 10px;
+  border: var(--border-in-light);
+  box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.03);
+  background-color: var(--white);
+  color: var(--black);
+  font-family: inherit;
+  padding: 10px 90px 10px 14px;
+  resize: none;
+  outline: none;
+  box-sizing: border-box;
+  min-height: 68px;
+
+  &:focus {
+    border: 1px solid var(--primary);
+  }
+}

+ 86 - 0
app/components/ui-lib.tsx

@@ -4,6 +4,9 @@ import CloseIcon from "../icons/close.svg";
 import EyeIcon from "../icons/eye.svg";
 import EyeOffIcon from "../icons/eye-off.svg";
 import DownIcon from "../icons/down.svg";
+import ConfirmIcon from "../icons/confirm.svg";
+import CancelIcon from "../icons/cancel.svg";
+
 import Locale from "../locales";
 
 import { createRoot } from "react-dom/client";
@@ -287,6 +290,10 @@ export function showConfirm(content: any) {
               resolve(false);
               closeModal();
             }}
+            icon={<CancelIcon />}
+            tabIndex={0}
+            bordered
+            shadow
           ></IconButton>,
           <IconButton
             key="confirm"
@@ -296,6 +303,11 @@ export function showConfirm(content: any) {
               resolve(true);
               closeModal();
             }}
+            icon={<ConfirmIcon />}
+            tabIndex={0}
+            autoFocus
+            bordered
+            shadow
           ></IconButton>,
         ]}
         onClose={closeModal}
@@ -305,3 +317,77 @@ export function showConfirm(content: any) {
     );
   });
 }
+
+function PromptInput(props: {
+  value: string;
+  onChange: (value: string) => void;
+}) {
+  const [input, setInput] = useState(props.value);
+  const onInput = (value: string) => {
+    props.onChange(value);
+    setInput(value);
+  };
+
+  return (
+    <textarea
+      className={styles["modal-input"]}
+      autoFocus
+      value={input}
+      onInput={(e) => onInput(e.currentTarget.value)}
+    ></textarea>
+  );
+}
+
+export function showPrompt(content: any, value = "") {
+  const div = document.createElement("div");
+  div.className = "modal-mask";
+  document.body.appendChild(div);
+
+  const root = createRoot(div);
+  const closeModal = () => {
+    root.unmount();
+    div.remove();
+  };
+
+  return new Promise<string>((resolve) => {
+    let userInput = "";
+
+    root.render(
+      <Modal
+        title={content}
+        actions={[
+          <IconButton
+            key="cancel"
+            text={Locale.UI.Cancel}
+            onClick={() => {
+              closeModal();
+            }}
+            icon={<CancelIcon />}
+            bordered
+            shadow
+            tabIndex={0}
+          ></IconButton>,
+          <IconButton
+            key="confirm"
+            text={Locale.UI.Confirm}
+            type="primary"
+            onClick={() => {
+              resolve(userInput);
+              closeModal();
+            }}
+            icon={<ConfirmIcon />}
+            bordered
+            shadow
+            tabIndex={0}
+          ></IconButton>,
+        ]}
+        onClose={closeModal}
+      >
+        <PromptInput
+          onChange={(val) => (userInput = val)}
+          value={value}
+        ></PromptInput>
+      </Modal>,
+    );
+  });
+}

File diff suppressed because it is too large
+ 0 - 0
app/icons/cancel.svg


File diff suppressed because it is too large
+ 0 - 0
app/icons/confirm.svg


+ 3 - 0
app/styles/globals.scss

@@ -304,6 +304,9 @@ pre {
   &:hover {
     filter: brightness(0.9);
   }
+  &:focus {
+    filter: brightness(0.95);
+  }
 }
 
 .error {

Some files were not shown because too many files changed in this diff