diff --git a/app/components/settings.module.scss b/app/components/settings.module.scss index 30abc36d..f257a3ca 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 385fc323..5d0a663f 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 208752c1..45dc10a9 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 1981944f..048e575c 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 d7357731..e424d9b4 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 783cd6e9..46d18a54 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 3fcc80ec..ee9a2c2b 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 4bbe0512..fb693cf5 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 a658fcc4..5eb4fe3e 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 9a0e9eac..de964fc3 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 e3a2eedd..98d4193b 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 acba064f..32e55921 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