From 0209ace221c1f2ba4a0bda096b25bad15573c218 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Mon, 1 May 2023 22:53:33 +0800 Subject: [PATCH 01/14] fix: #1154 wrong date range when query usage --- app/requests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/requests.ts b/app/requests.ts index 7e92cc45e..9c069ccb9 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -102,11 +102,11 @@ export async function requestUsage() { .getDate() .toString() .padStart(2, "0")}`; - const ONE_DAY = 2 * 24 * 60 * 60 * 1000; - const now = new Date(Date.now() + ONE_DAY); + const ONE_DAY = 1 * 24 * 60 * 60 * 1000; + const now = new Date(); const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); const startDate = formatDate(startOfMonth); - const endDate = formatDate(now); + const endDate = formatDate(new Date(Date.now() + ONE_DAY)); const [used, subs] = await Promise.all([ requestOpenaiClient( From c37885e743f02f7102816f0c96f86c124f3d8b1e Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Mon, 1 May 2023 23:21:28 +0800 Subject: [PATCH 02/14] fix: #1130 #1131 delete right session --- app/components/chat-list.tsx | 13 ++++-- app/components/sidebar.tsx | 6 ++- app/components/ui-lib.tsx | 8 +++- app/store/chat.ts | 89 ++++++++++++++++-------------------- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/app/components/chat-list.tsx b/app/components/chat-list.tsx index 2c7b95aa4..02ea086b2 100644 --- a/app/components/chat-list.tsx +++ b/app/components/chat-list.tsx @@ -67,7 +67,10 @@ export function ChatItem(props: { )} -
+
@@ -77,14 +80,14 @@ export function ChatItem(props: { } export function ChatList(props: { narrow?: boolean }) { - const [sessions, selectedIndex, selectSession, removeSession, moveSession] = - useChatStore((state) => [ + const [sessions, selectedIndex, selectSession, moveSession] = useChatStore( + (state) => [ state.sessions, state.currentSessionIndex, state.selectSession, - state.removeSession, state.moveSession, - ]); + ], + ); const chatStore = useChatStore(); const navigate = useNavigate(); diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx index 47a311725..776219641 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar.tsx @@ -138,7 +138,11 @@ export function SideBar(props: { className?: string }) {
} - onClick={chatStore.deleteSession} + onClick={() => { + if (confirm(Locale.Home.DeleteChat)) { + chatStore.deleteSession(chatStore.currentSessionIndex); + } + }} />
diff --git a/app/components/ui-lib.tsx b/app/components/ui-lib.tsx index 5b6ed9598..c16f94a42 100644 --- a/app/components/ui-lib.tsx +++ b/app/components/ui-lib.tsx @@ -158,6 +158,7 @@ export type ToastProps = { text: string; onClick: () => void; }; + onClose?: () => void; }; export function Toast(props: ToastProps) { @@ -167,7 +168,10 @@ export function Toast(props: ToastProps) { {props.content} {props.action && (
From 9f3188fe45d9d5c14abcb4d0a98b3b7a0718f1fe Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Mon, 1 May 2023 23:37:02 +0800 Subject: [PATCH 04/14] fix: #1124 mask model config does not works --- app/requests.ts | 20 ++++++-------------- app/store/chat.ts | 38 ++++++++++++++++++++------------------ app/store/config.ts | 1 - 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/app/requests.ts b/app/requests.ts index 9c069ccb9..582ab4862 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -14,9 +14,8 @@ const TIME_OUT_MS = 60000; const makeRequestParam = ( messages: Message[], options?: { - filterBot?: boolean; stream?: boolean; - model?: ModelType; + overrideModel?: ModelType; }, ): ChatRequest => { let sendMessages = messages.map((v) => ({ @@ -24,18 +23,14 @@ const makeRequestParam = ( content: v.content, })); - if (options?.filterBot) { - sendMessages = sendMessages.filter((m) => m.role !== "assistant"); - } - const modelConfig = { ...useAppConfig.getState().modelConfig, ...useChatStore.getState().currentSession().mask.modelConfig, }; // override model config - if (options?.model) { - modelConfig.model = options.model; + if (options?.overrideModel) { + modelConfig.model = options.overrideModel; } return { @@ -82,8 +77,7 @@ export async function requestChat( }, ) { const req: ChatRequest = makeRequestParam(messages, { - filterBot: true, - model: options?.model, + overrideModel: options?.model, }); const res = await requestOpenaiClient("v1/chat/completions")(req); @@ -149,9 +143,8 @@ export async function requestUsage() { export async function requestChatStream( messages: Message[], options?: { - filterBot?: boolean; modelConfig?: ModelConfig; - model?: ModelType; + overrideModel?: ModelType; onMessage: (message: string, done: boolean) => void; onError: (error: Error, statusCode?: number) => void; onController?: (controller: AbortController) => void; @@ -159,8 +152,7 @@ export async function requestChatStream( ) { const req = makeRequestParam(messages, { stream: true, - filterBot: options?.filterBot, - model: options?.model, + overrideModel: options?.overrideModel, }); console.log("[Request] ", req); diff --git a/app/store/chat.ts b/app/store/chat.ts index d1aeabf72..5abd81298 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -236,6 +236,9 @@ export const useChatStore = create()( }, async onUserInput(content) { + const session = get().currentSession(); + const modelConfig = session.mask.modelConfig; + const userMessage: Message = createMessage({ role: "user", content, @@ -245,7 +248,7 @@ export const useChatStore = create()( role: "assistant", streaming: true, id: userMessage.id! + 1, - model: useAppConfig.getState().modelConfig.model, + model: modelConfig.model, }); // get recent messages @@ -279,14 +282,16 @@ export const useChatStore = create()( } }, onError(error, statusCode) { + const isAborted = error.message.includes("aborted"); if (statusCode === 401) { botMessage.content = Locale.Error.Unauthorized; - } else if (!error.message.includes("aborted")) { + } else if (!isAborted) { botMessage.content += "\n\n" + Locale.Store.Error; } botMessage.streaming = false; - userMessage.isError = true; - botMessage.isError = true; + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + set(() => ({})); ControllerPool.remove(sessionIndex, botMessage.id ?? messageIndex); }, @@ -298,8 +303,7 @@ export const useChatStore = create()( controller, ); }, - filterBot: !useAppConfig.getState().sendBotMessages, - modelConfig: useAppConfig.getState().modelConfig, + modelConfig: { ...modelConfig }, }); }, @@ -318,7 +322,7 @@ export const useChatStore = create()( getMessagesWithMemory() { const session = get().currentSession(); - const config = useAppConfig.getState(); + const modelConfig = session.mask.modelConfig; const messages = session.messages.filter((msg) => !msg.isError); const n = messages.length; @@ -326,7 +330,7 @@ export const useChatStore = create()( // long term memory if ( - session.mask.modelConfig.sendMemory && + modelConfig.sendMemory && session.memoryPrompt && session.memoryPrompt.length > 0 ) { @@ -337,14 +341,14 @@ export const useChatStore = create()( // get short term and unmemoried long term memory const shortTermMemoryMessageIndex = Math.max( 0, - n - config.modelConfig.historyMessageCount, + n - modelConfig.historyMessageCount, ); const longTermMemoryMessageIndex = session.lastSummarizeIndex; const oldestIndex = Math.max( shortTermMemoryMessageIndex, longTermMemoryMessageIndex, ); - const threshold = config.modelConfig.compressMessageLengthThreshold; + const threshold = modelConfig.compressMessageLengthThreshold; // get recent messages as many as possible const reversedRecentMessages = []; @@ -403,17 +407,17 @@ export const useChatStore = create()( }); } - const config = useAppConfig.getState(); + const modelConfig = session.mask.modelConfig; let toBeSummarizedMsgs = session.messages.slice( session.lastSummarizeIndex, ); const historyMsgLength = countMessages(toBeSummarizedMsgs); - if (historyMsgLength > config?.modelConfig?.max_tokens ?? 4000) { + if (historyMsgLength > modelConfig?.max_tokens ?? 4000) { const n = toBeSummarizedMsgs.length; toBeSummarizedMsgs = toBeSummarizedMsgs.slice( - Math.max(0, n - config.modelConfig.historyMessageCount), + Math.max(0, n - modelConfig.historyMessageCount), ); } @@ -426,12 +430,11 @@ export const useChatStore = create()( "[Chat History] ", toBeSummarizedMsgs, historyMsgLength, - config.modelConfig.compressMessageLengthThreshold, + modelConfig.compressMessageLengthThreshold, ); if ( - historyMsgLength > - config.modelConfig.compressMessageLengthThreshold && + historyMsgLength > modelConfig.compressMessageLengthThreshold && session.mask.modelConfig.sendMemory ) { requestChatStream( @@ -441,8 +444,7 @@ export const useChatStore = create()( date: "", }), { - filterBot: false, - model: "gpt-3.5-turbo", + overrideModel: "gpt-3.5-turbo", onMessage(message, done) { session.memoryPrompt = message; if (done) { diff --git a/app/store/config.ts b/app/store/config.ts index 4bd68b732..da77c7b3b 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -17,7 +17,6 @@ export enum Theme { } export const DEFAULT_CONFIG = { - sendBotMessages: true as boolean, submitKey: SubmitKey.CtrlEnter as SubmitKey, avatar: "1f603", fontSize: 14, From 1aaf4ae5bc30309de7e1d8aea1df0fe413e11c45 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Mon, 1 May 2023 23:39:54 +0800 Subject: [PATCH 05/14] fix: #1126 can not select prompt --- app/components/chat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 8fc39e31d..4c1686690 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -391,7 +391,7 @@ export function Chat() { const onPromptSelect = (prompt: Prompt) => { setPromptHints([]); inputRef.current?.focus(); - setUserInput(prompt.content); + setTimeout(() => setUserInput(prompt.content), 60); }; // auto grow input From 8f5c28981877c3428b29fb08c36a3c15117c873d Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Mon, 1 May 2023 23:48:23 +0800 Subject: [PATCH 06/14] fix: #751 do not cache request --- app/api/common.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/api/common.ts b/app/api/common.ts index 22e71884f..a86d68617 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -26,8 +26,11 @@ export async function requestOpenai(req: NextRequest) { headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, - ...(process.env.OPENAI_ORG_ID && { "OpenAI-Organization": process.env.OPENAI_ORG_ID }), + ...(process.env.OPENAI_ORG_ID && { + "OpenAI-Organization": process.env.OPENAI_ORG_ID, + }), }, + cache: "no-store", method: req.method, body: req.body, }); From a69cec89fb3b4264abaaa9537c5351bbe7860882 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 00:31:44 +0800 Subject: [PATCH 07/14] perf: close #909 reduce message items render time --- app/components/chat.tsx | 11 ++-- app/components/markdown.tsx | 107 +++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 4c1686690..bd2c913d2 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1,5 +1,5 @@ import { useDebouncedCallback } from "use-debounce"; -import { memo, useState, useRef, useEffect, useLayoutEffect } from "react"; +import { useState, useRef, useEffect, useLayoutEffect } from "react"; import SendWhiteIcon from "../icons/send-white.svg"; import BrainIcon from "../icons/brain.svg"; @@ -64,12 +64,9 @@ import { useMaskStore, } from "../store/mask"; -const Markdown = dynamic( - async () => memo((await import("./markdown")).Markdown), - { - loading: () => , - }, -); +const Markdown = dynamic(async () => (await import("./markdown")).Markdown, { + loading: () => , +}); function exportMessages(messages: Message[], topic: string) { const mdText = diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 25d0584f6..2909293c7 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -9,6 +9,7 @@ import { useRef, useState, RefObject, useEffect } from "react"; import { copyToClipboard } from "../utils"; import LoadingIcon from "../icons/three-dots.svg"; +import React from "react"; export function PreCode(props: { children: any }) { const ref = useRef(null); @@ -29,6 +30,32 @@ export function PreCode(props: { children: any }) { ); } +function _MarkDownContent(props: { content: string }) { + return ( + + {props.content} + + ); +} + +export const MarkdownContent = React.memo(_MarkDownContent); + export function Markdown( props: { content: string; @@ -38,69 +65,49 @@ export function Markdown( } & React.DOMAttributes, ) { const mdRef = useRef(null); + const renderedHeight = useRef(0); + const inView = useRef(false); const parent = props.parentRef.current; const md = mdRef.current; - const rendered = useRef(true); // disable lazy loading for bad ux - const [counter, setCounter] = useState(0); - useEffect(() => { - // to triggr rerender - setCounter(counter + 1); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.loading]); + if (parent && md) { + const parentBounds = parent.getBoundingClientRect(); + const twoScreenHeight = Math.max(500, parentBounds.height * 2); + const mdBounds = md.getBoundingClientRect(); + const isInRange = (x: number) => + x <= parentBounds.bottom + twoScreenHeight && + x >= parentBounds.top - twoScreenHeight; + inView.current = isInRange(mdBounds.top) || isInRange(mdBounds.bottom); + } - const inView = - rendered.current || - (() => { - if (parent && md) { - const parentBounds = parent.getBoundingClientRect(); - const mdBounds = md.getBoundingClientRect(); - const isInRange = (x: number) => - x <= parentBounds.bottom && x >= parentBounds.top; - const inView = isInRange(mdBounds.top) || isInRange(mdBounds.bottom); - - if (inView) { - rendered.current = true; - } - - return inView; - } - })(); - - const shouldLoading = props.loading || !inView; + if (inView.current && md) { + renderedHeight.current = Math.max( + renderedHeight.current, + md.getBoundingClientRect().height, + ); + } return (
0 + ? renderedHeight.current + : "auto", + }} ref={mdRef} onContextMenu={props.onContextMenu} onDoubleClickCapture={props.onDoubleClickCapture} > - {shouldLoading ? ( - - ) : ( - - {props.content} - - )} + {inView.current && + (props.loading ? ( + + ) : ( + + ))}
); } From e509749421dc7d81180bc3f4255dae27712defc6 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 02:26:43 +0800 Subject: [PATCH 08/14] perf: improve prompt list performance --- app/components/settings.module.scss | 71 ++++++++------ app/components/settings.tsx | 144 +++++++++++++++++++--------- app/locales/cn.ts | 13 ++- app/locales/de.ts | 11 +++ app/locales/en.ts | 11 +++ app/locales/es.ts | 11 +++ app/locales/it.ts | 11 +++ app/locales/jp.ts | 11 +++ app/locales/tr.ts | 11 +++ app/locales/tw.ts | 10 ++ app/store/prompt.ts | 15 ++- scripts/init-proxy.sh | 1 + 12 files changed, 240 insertions(+), 80 deletions(-) diff --git a/app/components/settings.module.scss b/app/components/settings.module.scss index 30abc36df..f257a3ca4 100644 --- a/app/components/settings.module.scss +++ b/app/components/settings.module.scss @@ -7,6 +7,20 @@ cursor: pointer; } +.edit-prompt-modal { + display: flex; + flex-direction: column; + + .edit-prompt-title { + max-width: unset; + margin-bottom: 20px; + text-align: left; + } + .edit-prompt-content { + max-width: unset; + } +} + .user-prompt-modal { min-height: 40vh; @@ -18,47 +32,42 @@ } .user-prompt-list { - padding: 10px 0; + border: var(--border-in-light); + border-radius: 10px; .user-prompt-item { - margin-bottom: 10px; - widows: 100%; + display: flex; + justify-content: space-between; + padding: 10px; + + &:not(:last-child) { + border-bottom: var(--border-in-light); + } .user-prompt-header { - display: flex; - widows: 100%; - margin-bottom: 5px; + max-width: calc(100% - 100px); .user-prompt-title { - flex-grow: 1; - max-width: 100%; - margin-right: 5px; - padding: 5px; - font-size: 12px; - text-align: left; + font-size: 14px; + line-height: 2; + font-weight: bold; } - - .user-prompt-buttons { - display: flex; - align-items: center; - - .user-prompt-button { - height: 100%; - - &:not(:last-child) { - margin-right: 5px; - } - } + .user-prompt-content { + font-size: 12px; } } - .user-prompt-content { - width: 100%; - box-sizing: border-box; - padding: 5px; - margin-right: 10px; - font-size: 12px; - flex-grow: 1; + .user-prompt-buttons { + display: flex; + align-items: center; + + .user-prompt-button { + height: 100%; + + &:not(:last-child) { + margin-right: 5px; + } + } } } } diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 385fc323b..5d0a663fe 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -3,10 +3,12 @@ import { useState, useEffect, useMemo, HTMLProps, useRef } from "react"; import styles from "./settings.module.scss"; import ResetIcon from "../icons/reload.svg"; +import AddIcon from "../icons/add.svg"; import CloseIcon from "../icons/close.svg"; import CopyIcon from "../icons/copy.svg"; import ClearIcon from "../icons/clear.svg"; import EditIcon from "../icons/edit.svg"; +import EyeIcon from "../icons/eye.svg"; import { Input, List, ListItem, Modal, PasswordInput, Popover } from "./ui-lib"; import { ModelConfigList } from "./model-config"; @@ -30,6 +32,55 @@ import { InputRange } from "./input-range"; import { useNavigate } from "react-router-dom"; import { Avatar, AvatarPicker } from "./emoji"; +function EditPromptModal(props: { id: number; onClose: () => void }) { + const promptStore = usePromptStore(); + const prompt = promptStore.get(props.id); + + return prompt ? ( +
+ , + ]} + > +
+ + promptStore.update( + props.id, + (prompt) => (prompt.title = e.currentTarget.value), + ) + } + > + + promptStore.update( + props.id, + (prompt) => (prompt.content = e.currentTarget.value), + ) + } + > +
+
+
+ ) : null; +} + function UserPromptModal(props: { onClose?: () => void }) { const promptStore = usePromptStore(); const userPrompts = promptStore.getUserPrompts(); @@ -39,6 +90,8 @@ function UserPromptModal(props: { onClose?: () => void }) { const [searchPrompts, setSearchPrompts] = useState([]); const prompts = searchInput.length > 0 ? searchPrompts : allPrompts; + const [editingPromptId, setEditingPromptId] = useState(); + useEffect(() => { if (searchInput.length > 0) { const searchResult = SearchService.search(searchInput); @@ -56,8 +109,13 @@ function UserPromptModal(props: { onClose?: () => void }) { actions={[ promptStore.add({ title: "", content: "" })} - icon={} + onClick={() => + promptStore.add({ + title: "Empty Prompt", + content: "Empty Prompt Content", + }) + } + icon={} bordered text={Locale.Settings.Prompt.Modal.Add} />, @@ -76,57 +134,51 @@ function UserPromptModal(props: { onClose?: () => void }) { {prompts.map((v, _) => (
- { - if (v.isUser) { - promptStore.updateUserPrompts( - v.id!, - (prompt) => (prompt.title = e.currentTarget.value), - ); - } - }} - > - -
- {v.isUser && ( - } - bordered - className={styles["user-prompt-button"]} - onClick={() => promptStore.remove(v.id!)} - /> - )} - } - bordered - className={styles["user-prompt-button"]} - onClick={() => copyToClipboard(v.content)} - /> +
{v.title}
+
+ {v.content}
- { - if (v.isUser) { - promptStore.updateUserPrompts( - v.id!, - (prompt) => (prompt.content = e.currentTarget.value), - ); - } - }} - /> + +
+ {v.isUser && ( + } + className={styles["user-prompt-button"]} + onClick={() => promptStore.remove(v.id!)} + /> + )} + {v.isUser ? ( + } + className={styles["user-prompt-button"]} + onClick={() => setEditingPromptId(v.id)} + /> + ) : ( + } + className={styles["user-prompt-button"]} + onClick={() => setEditingPromptId(v.id)} + /> + )} + } + className={styles["user-prompt-button"]} + onClick={() => copyToClipboard(v.content)} + /> +
))}
+ + {editingPromptId !== undefined && ( + setEditingPromptId(undefined)} + /> + )} ); } diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 208752c17..45dc10a92 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -116,9 +116,12 @@ const cn = { Edit: "编辑", Modal: { Title: "提示词列表", - Add: "增加一条", + Add: "新建", Search: "搜索提示词", }, + EditModal: { + Title: "编辑提示词", + }, }, HistoryCount: { Title: "附带历史消息数", @@ -223,6 +226,14 @@ const cn = { SubTitle: "现在开始,与面具背后的灵魂思维碰撞", More: "搜索更多", }, + + UI: { + Confirm: "确认", + Cancel: "取消", + Close: "关闭", + Create: "新建", + Edit: "编辑", + }, }; export type LocaleType = typeof cn; diff --git a/app/locales/de.ts b/app/locales/de.ts index 1981944fb..048e575c5 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -121,6 +121,9 @@ const de: LocaleType = { Add: "Add One", Search: "Search Prompts", }, + EditModal: { + Title: "Edit Prompt", + }, }, HistoryCount: { Title: "Anzahl der angehängten Nachrichten", @@ -230,6 +233,14 @@ const de: LocaleType = { NotShow: "Not Show Again", ConfirmNoShow: "Confirm to disable?You can enable it in settings later.", }, + + UI: { + Confirm: "Confirm", + Cancel: "Cancel", + Close: "Close", + Create: "Create", + Edit: "Edit", + }, }; export default de; diff --git a/app/locales/en.ts b/app/locales/en.ts index d73577318..e424d9b47 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -120,6 +120,9 @@ const en: LocaleType = { Add: "Add One", Search: "Search Prompts", }, + EditModal: { + Title: "Edit Prompt", + }, }, HistoryCount: { Title: "Attached Messages Count", @@ -226,6 +229,14 @@ const en: LocaleType = { NotShow: "Not Show Again", ConfirmNoShow: "Confirm to disable?You can enable it in settings later.", }, + + UI: { + Confirm: "Confirm", + Cancel: "Cancel", + Close: "Close", + Create: "Create", + Edit: "Edit", + }, }; export default en; diff --git a/app/locales/es.ts b/app/locales/es.ts index 783cd6e95..46d18a547 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -120,6 +120,9 @@ const es: LocaleType = { Add: "Add One", Search: "Search Prompts", }, + EditModal: { + Title: "Edit Prompt", + }, }, HistoryCount: { Title: "Cantidad de mensajes adjuntos", @@ -227,6 +230,14 @@ const es: LocaleType = { NotShow: "Not Show Again", ConfirmNoShow: "Confirm to disable?You can enable it in settings later.", }, + + UI: { + Confirm: "Confirm", + Cancel: "Cancel", + Close: "Close", + Create: "Create", + Edit: "Edit", + }, }; export default es; diff --git a/app/locales/it.ts b/app/locales/it.ts index 3fcc80ec9..ee9a2c2bc 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -120,6 +120,9 @@ const it: LocaleType = { Add: "Add One", Search: "Search Prompts", }, + EditModal: { + Title: "Edit Prompt", + }, }, HistoryCount: { Title: "Conteggio dei messaggi allegati", @@ -228,6 +231,14 @@ const it: LocaleType = { NotShow: "Not Show Again", ConfirmNoShow: "Confirm to disable?You can enable it in settings later.", }, + + UI: { + Confirm: "Confirm", + Cancel: "Cancel", + Close: "Close", + Create: "Create", + Edit: "Edit", + }, }; export default it; diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 4bbe05125..fb693cf5b 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -122,6 +122,9 @@ const jp: LocaleType = { Add: "新規追加", Search: "プロンプトワード検索", }, + EditModal: { + Title: "编辑提示词", + }, }, HistoryCount: { Title: "履歴メッセージ数を添付", @@ -226,6 +229,14 @@ const jp: LocaleType = { NotShow: "不再展示", ConfirmNoShow: "确认禁用?禁用后可以随时在设置中重新启用。", }, + + UI: { + Confirm: "确认", + Cancel: "取消", + Close: "关闭", + Create: "新建", + Edit: "编辑", + }, }; export default jp; diff --git a/app/locales/tr.ts b/app/locales/tr.ts index a658fcc4f..5eb4fe3e4 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -120,6 +120,9 @@ const tr: LocaleType = { Add: "Add One", Search: "Search Prompts", }, + EditModal: { + Title: "Edit Prompt", + }, }, HistoryCount: { Title: "Ekli Mesaj Sayısı", @@ -228,6 +231,14 @@ const tr: LocaleType = { NotShow: "Not Show Again", ConfirmNoShow: "Confirm to disable?You can enable it in settings later.", }, + + UI: { + Confirm: "Confirm", + Cancel: "Cancel", + Close: "Close", + Create: "Create", + Edit: "Edit", + }, }; export default tr; diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 9a0e9eac9..de964fc3f 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -118,6 +118,9 @@ const tw: LocaleType = { Add: "新增一條", Search: "搜尋提示詞", }, + EditModal: { + Title: "编辑提示词", + }, }, HistoryCount: { Title: "附帶歷史訊息數", @@ -219,6 +222,13 @@ const tw: LocaleType = { NotShow: "不再展示", ConfirmNoShow: "确认禁用?禁用后可以随时在设置中重新启用。", }, + UI: { + Confirm: "确认", + Cancel: "取消", + Close: "关闭", + Create: "新建", + Edit: "编辑", + }, }; export default tw; diff --git a/app/store/prompt.ts b/app/store/prompt.ts index e3a2eeddc..98d4193be 100644 --- a/app/store/prompt.ts +++ b/app/store/prompt.ts @@ -17,11 +17,12 @@ export interface PromptStore { prompts: Record; add: (prompt: Prompt) => number; + get: (id: number) => Prompt | undefined; remove: (id: number) => void; search: (text: string) => Prompt[]; + update: (id: number, updater: (prompt: Prompt) => void) => void; getUserPrompts: () => Prompt[]; - updateUserPrompts: (id: number, updater: (prompt: Prompt) => void) => void; } export const SearchService = { @@ -81,6 +82,16 @@ export const usePromptStore = create()( return prompt.id!; }, + get(id) { + const targetPrompt = get().prompts[id]; + + if (!targetPrompt) { + return SearchService.builtinPrompts.find((v) => v.id === id); + } + + return targetPrompt; + }, + remove(id) { const prompts = get().prompts; delete prompts[id]; @@ -98,7 +109,7 @@ export const usePromptStore = create()( return userPrompts; }, - updateUserPrompts(id: number, updater) { + update(id: number, updater) { const prompt = get().prompts[id] ?? { title: "", content: "", diff --git a/scripts/init-proxy.sh b/scripts/init-proxy.sh index acba064f4..32e55921a 100644 --- a/scripts/init-proxy.sh +++ b/scripts/init-proxy.sh @@ -1,5 +1,6 @@ dir="$(dirname "$0")" config=$dir/proxychains.conf host_ip=$(grep nameserver /etc/resolv.conf | sed 's/nameserver //') +echo "proxying to $host_ip" cp $dir/proxychains.template.conf $config sed -i "\$s/.*/http $host_ip 7890/" $config From 220c622f8f472311f4d3787e1293998c475ad0e3 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 02:37:15 +0800 Subject: [PATCH 09/14] fixup --- app/components/markdown.tsx | 43 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 2909293c7..11fc249df 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -71,22 +71,35 @@ export function Markdown( const parent = props.parentRef.current; const md = mdRef.current; - if (parent && md) { - const parentBounds = parent.getBoundingClientRect(); - const twoScreenHeight = Math.max(500, parentBounds.height * 2); - const mdBounds = md.getBoundingClientRect(); - const isInRange = (x: number) => - x <= parentBounds.bottom + twoScreenHeight && - x >= parentBounds.top - twoScreenHeight; - inView.current = isInRange(mdBounds.top) || isInRange(mdBounds.bottom); - } + const checkInView = () => { + if (parent && md) { + const parentBounds = parent.getBoundingClientRect(); + const twoScreenHeight = Math.max(500, parentBounds.height * 2); + const mdBounds = md.getBoundingClientRect(); + const isInRange = (x: number) => + x <= parentBounds.bottom + twoScreenHeight && + x >= parentBounds.top - twoScreenHeight; + inView.current = isInRange(mdBounds.top) || isInRange(mdBounds.bottom); + } - if (inView.current && md) { - renderedHeight.current = Math.max( - renderedHeight.current, - md.getBoundingClientRect().height, - ); - } + if (inView.current && md) { + renderedHeight.current = Math.max( + renderedHeight.current, + md.getBoundingClientRect().height, + ); + } + }; + + useEffect(() => { + setTimeout(() => { + if (!inView.current) { + checkInView(); + } + }, 10); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + checkInView(); return (
Date: Tue, 2 May 2023 02:38:30 +0800 Subject: [PATCH 10/14] fixup --- app/components/markdown.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 11fc249df..69bc35175 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -90,15 +90,6 @@ export function Markdown( } }; - useEffect(() => { - setTimeout(() => { - if (!inView.current) { - checkInView(); - } - }, 10); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - checkInView(); return ( From ae8050a3f72e370cdec0c64b645ef57e4df650cf Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 02:45:15 +0800 Subject: [PATCH 11/14] fixup --- app/components/markdown.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 69bc35175..eefb31f30 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -90,6 +90,15 @@ export function Markdown( } }; + useEffect(() => { + setTimeout(() => { + if (!inView.current) { + checkInView(); + } + }, 30); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + checkInView(); return ( From 116e16e30dfda4ffd9aea5e006d78db525a323d3 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 02:52:25 +0800 Subject: [PATCH 12/14] fixup --- app/components/chat.tsx | 1 + app/components/markdown.tsx | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index bd2c913d2..4aaa8437f 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -725,6 +725,7 @@ export function Chat() { }} fontSize={fontSize} parentRef={scrollRef} + defaultShow={i >= messages.length - 10} />
{!isUser && !message.preview && ( diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index eefb31f30..b5805e503 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -62,11 +62,12 @@ export function Markdown( loading?: boolean; fontSize?: number; parentRef: RefObject; + defaultShow?: boolean; } & React.DOMAttributes, ) { const mdRef = useRef(null); const renderedHeight = useRef(0); - const inView = useRef(false); + const inView = useRef(!!props.defaultShow); const parent = props.parentRef.current; const md = mdRef.current; @@ -90,15 +91,6 @@ export function Markdown( } }; - useEffect(() => { - setTimeout(() => { - if (!inView.current) { - checkInView(); - } - }, 30); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - checkInView(); return ( From 132f6c842073d354f7c88fc06fa18d705a978717 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 03:01:42 +0800 Subject: [PATCH 13/14] feat: improve mask ui --- app/components/mask.module.scss | 9 +++------ app/components/mask.tsx | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/components/mask.module.scss b/app/components/mask.module.scss index 0618cc065..c1778d454 100644 --- a/app/components/mask.module.scss +++ b/app/components/mask.module.scss @@ -23,8 +23,9 @@ .mask-filter { width: 100%; max-width: 100%; - margin-bottom: 10px; + margin-bottom: 20px; animation: search-in ease 0.3s; + height: 40px; display: flex; @@ -32,7 +33,6 @@ flex-grow: 1; max-width: 100%; min-width: 0; - margin-bottom: 20px; animation: search-in ease 0.3s; } @@ -45,10 +45,7 @@ height: 100%; margin-left: 10px; box-sizing: border-box; - - button { - padding: 10px; - } + min-width: 80px; } } diff --git a/app/components/mask.tsx b/app/components/mask.tsx index 3f239aca5..c980c48c6 100644 --- a/app/components/mask.tsx +++ b/app/components/mask.tsx @@ -291,17 +291,16 @@ export function MaskPage() { ))} -
- } - text={Locale.Mask.Page.Create} - bordered - onClick={() => { - const createdMask = maskStore.create(); - setEditingMaskId(createdMask.id); - }} - /> -
+ } + text={Locale.Mask.Page.Create} + bordered + onClick={() => { + const createdMask = maskStore.create(); + setEditingMaskId(createdMask.id); + }} + />
From 717c123b82e5b20e27b1bd29849ba4f64bbd9b6b Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Tue, 2 May 2023 03:10:13 +0800 Subject: [PATCH 14/14] feat: improve mask ui --- app/components/mask.module.scss | 15 +-------------- app/components/new-chat.module.scss | 5 ++--- app/components/new-chat.tsx | 23 +++++++++++++---------- app/locales/cn.ts | 2 +- 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/app/components/mask.module.scss b/app/components/mask.module.scss index c1778d454..d66d98864 100644 --- a/app/components/mask.module.scss +++ b/app/components/mask.module.scss @@ -1,16 +1,4 @@ @import "../styles/animation.scss"; - -@keyframes search-in { - from { - opacity: 0; - transform: translateY(5vh) scaleX(0.5); - } - to { - opacity: 1; - transform: translateY(0) scaleX(1); - } -} - .mask-page { height: 100%; display: flex; @@ -24,7 +12,7 @@ width: 100%; max-width: 100%; margin-bottom: 20px; - animation: search-in ease 0.3s; + animation: slide-in ease 0.3s; height: 40px; display: flex; @@ -33,7 +21,6 @@ flex-grow: 1; max-width: 100%; min-width: 0; - animation: search-in ease 0.3s; } .mask-filter-lang { diff --git a/app/components/new-chat.module.scss b/app/components/new-chat.module.scss index 36f447bba..b0e472ea5 100644 --- a/app/components/new-chat.module.scss +++ b/app/components/new-chat.module.scss @@ -59,10 +59,9 @@ display: flex; justify-content: center; - .search-bar { + .more { font-size: 12px; - margin-right: 10px; - width: 40vw; + margin-left: 10px; } } diff --git a/app/components/new-chat.tsx b/app/components/new-chat.tsx index 8cb4d35e6..42612e0ad 100644 --- a/app/components/new-chat.tsx +++ b/app/components/new-chat.tsx @@ -5,10 +5,11 @@ import { EmojiAvatar } from "./emoji"; import styles from "./new-chat.module.scss"; import LeftIcon from "../icons/left.svg"; -import AddIcon from "../icons/lightning.svg"; +import LightningIcon from "../icons/lightning.svg"; +import EyeIcon from "../icons/eye.svg"; import { useLocation, useNavigate } from "react-router-dom"; -import { createEmptyMask, Mask, useMaskStore } from "../store/mask"; +import { Mask, useMaskStore } from "../store/mask"; import Locale from "../locales"; import { useAppConfig, useChatStore } from "../store"; import { MaskAvatar } from "./mask"; @@ -148,20 +149,22 @@ export function NewChat() {
{Locale.NewChat.SubTitle}
- navigate(Path.Masks)} - /> - startChat()} - icon={} + icon={} type="primary" shadow /> + + navigate(Path.Masks)} + icon={} + bordered + shadow + />
diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 45dc10a92..f973dfbc9 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -224,7 +224,7 @@ const cn = { ConfirmNoShow: "确认禁用?禁用后可以随时在设置中重新启用。", Title: "挑选一个面具", SubTitle: "现在开始,与面具背后的灵魂思维碰撞", - More: "搜索更多", + More: "查看全部", }, UI: {