diff --git a/app/components/button.tsx b/app/components/button.tsx index f40a4e8f..2e5707ae 100644 --- a/app/components/button.tsx +++ b/app/components/button.tsx @@ -8,6 +8,7 @@ export function IconButton(props: { text?: string; bordered?: boolean; shadow?: boolean; + noDark?: boolean; className?: string; title?: string; }) { @@ -23,7 +24,11 @@ export function IconButton(props: { title={props.title} role="button" > -
{props.icon}
+
+ {props.icon} +
{props.text && (
{props.text}
)} diff --git a/app/components/chat.module.scss b/app/components/chat.module.scss index b52baa12..5216fb25 100644 --- a/app/components/chat.module.scss +++ b/app/components/chat.module.scss @@ -1,3 +1,5 @@ +@import "../styles/animation.scss"; + .prompt-toast { position: absolute; bottom: -50px; @@ -19,6 +21,8 @@ padding: 10px 20px; border-radius: 100px; + animation: slide-in-from-top ease 0.3s; + .prompt-toast-content { margin-left: 10px; } diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 4a80fe14..b35cd3eb 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -51,7 +51,7 @@ const Emoji = dynamic(async () => (await import("emoji-picker-react")).Emoji, { export function Avatar(props: { role: Message["role"] }) { const config = useChatStore((state) => state.config); - if (props.role === "assistant") { + if (props.role !== "user") { return ; } @@ -99,7 +99,8 @@ function exportMessages(messages: Message[], topic: string) { } function PromptToast(props: { - showModal: boolean; + showToast?: boolean; + showModal?: boolean; setShowModal: (_: boolean) => void; }) { const chatStore = useChatStore(); @@ -126,16 +127,18 @@ function PromptToast(props: { return (
-
props.setShowModal(true)} - > - - - {Locale.Context.Toast(context.length)} - -
+ {props.showToast && ( +
props.setShowModal(true)} + > + + + {Locale.Context.Toast(context.length)} + +
+ )} {props.showModal && (
} className={chatStyle["context-delete-button"]} onClick={() => removeContextPrompt(i)} + bordered />
))} @@ -281,7 +285,7 @@ function useScrollToBottom() { useLayoutEffect(() => { const dom = scrollRef.current; if (dom && autoScroll) { - setTimeout(() => (dom.scrollTop = dom.scrollHeight), 500); + setTimeout(() => (dom.scrollTop = dom.scrollHeight), 1); } }); @@ -310,6 +314,12 @@ export function Chat(props: { const [isLoading, setIsLoading] = useState(false); const { submitKey, shouldSubmit } = useSubmitHandler(); const { scrollRef, setAutoScroll } = useScrollToBottom(); + const [hitBottom, setHitBottom] = useState(false); + + const onChatBodyScroll = (e: HTMLElement) => { + const isTouchBottom = e.scrollTop + e.clientHeight >= e.scrollHeight - 20; + setHitBottom(isTouchBottom); + }; // prompt hints const promptStore = usePromptStore(); @@ -505,12 +515,17 @@ export function Chat(props: {
-
+
onChatBodyScroll(e.currentTarget)} + > {messages.map((message, i) => { const isUser = message.role === "user"; @@ -612,7 +627,8 @@ export function Chat(props: { } text={Locale.Chat.Send} - className={styles["chat-input-send"] + " no-dark"} + className={styles["chat-input-send"]} + noDark onClick={onUserSubmit} />
diff --git a/app/components/home.module.scss b/app/components/home.module.scss index 24b1f1bf..95964ae1 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -1,4 +1,5 @@ @import "./window.scss"; +@import "../styles/animation.scss"; @mixin container { background-color: var(--white); @@ -73,7 +74,7 @@ .sidebar { position: absolute; left: -100%; - z-index: 999; + z-index: 1000; height: var(--full-height); transition: all ease 0.3s; box-shadow: none; @@ -132,18 +133,6 @@ overflow: hidden; } -@keyframes slide-in { - from { - opacity: 0; - transform: translateY(20px); - } - - to { - opacity: 1; - transform: translateY(0px); - } -} - .chat-item:hover { background-color: var(--hover-color); } diff --git a/app/components/ui-lib.module.scss b/app/components/ui-lib.module.scss index 5c7925b0..4aa83662 100644 --- a/app/components/ui-lib.module.scss +++ b/app/components/ui-lib.module.scss @@ -1,3 +1,5 @@ +@import "../styles/animation.scss"; + .card { background-color: var(--white); border-radius: 10px; @@ -24,18 +26,6 @@ height: 100vh; } -@keyframes slide-in { - from { - transform: translateY(10px); - opacity: 0; - } - - to { - transform: translateY(0); - opacity: 1; - } -} - .list-item { display: flex; justify-content: space-between; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 2feed51a..a0e1da7a 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -35,7 +35,7 @@ const cn = { Download: "下载文件", }, Memory: { - Title: "上下文记忆 Prompt", + Title: "历史记忆", EmptyContent: "尚未记忆", Copy: "全部复制", }, diff --git a/app/styles/animation.scss b/app/styles/animation.scss new file mode 100644 index 00000000..b423b08a --- /dev/null +++ b/app/styles/animation.scss @@ -0,0 +1,23 @@ +@keyframes slide-in { + from { + opacity: 0; + transform: translateY(20px); + } + + to { + opacity: 1; + transform: translateY(0px); + } +} + +@keyframes slide-in-from-top { + from { + opacity: 0; + transform: translateY(-20px); + } + + to { + opacity: 1; + transform: translateY(0px); + } +}