diff --git a/app/components/home.module.scss b/app/components/home.module.scss index 87231feee..38c432ff5 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -169,13 +169,38 @@ transition: all ease 0.3s; opacity: 0; } +.chat-item-edit { + position: absolute; + top: 11px; + right: -25px; + transition: all ease 0.3s; + opacity: 0; +} +.chat-item-edit-input[type=text] { + font-size: 14px; + color: black; + font-weight: bolder; + padding: 0; + box-sizing: border-box; + width: 100%; + height: 100%; + border: 1px rgb(29,147,171) solid; + outline: none; + +} .chat-item:hover > .chat-item-delete { opacity: 0.5; right: 10px; } -.chat-item:hover > .chat-item-delete:hover { +.chat-item:hover > .chat-item-edit { + opacity: 0.5; + right: 35px; +} + +.chat-item:hover > .chat-item-delete, +.chat-item:hover > .chat-item-edit { opacity: 1; } diff --git a/app/components/home.tsx b/app/components/home.tsx index da65b1d63..5b95811cf 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -15,6 +15,7 @@ import ExportIcon from "../icons/export.svg"; import BotIcon from "../icons/bot.svg"; import AddIcon from "../icons/add.svg"; import DeleteIcon from "../icons/delete.svg"; +import EditIcon from "../icons/edit-title.svg"; import LoadingIcon from "../icons/three-dots.svg"; import MenuIcon from "../icons/menu.svg"; import CloseIcon from "../icons/close.svg"; @@ -69,11 +70,16 @@ export function Avatar(props: { role: Message["role"] }) { export function ChatItem(props: { onClick?: () => void; onDelete?: () => void; + onEdit?: (title: string) => void; title: string; count: number; time: string; selected: boolean; }) { + const [dialog, setDialog] = useState({ + isEdit: false, + title: props.title, + }); return (
-
{props.title}
+
+ {dialog.isEdit ? ( + { + setDialog({ + ...dialog, + title: data.target.value, + }); + }} + onBlur={editCompleted} + onKeyDown={(event) => { + if (event.key === "Enter") { + editCompleted(); + } + }} + /> + ) : ( +
{dialog.title}
+ )} +
{Locale.ChatItem.ChatItemCount(props.count)} @@ -91,19 +120,41 @@ export function ChatItem(props: {
+
+ +
); + + function editStart() { + setDialog({ + ...dialog, + isEdit: true, + }); + } + function editCompleted() { + setDialog({ + ...dialog, + isEdit: false, + }); + props.onEdit && props.onEdit(dialog.title); + } } export function ChatList() { - const [sessions, selectedIndex, selectSession, removeSession] = useChatStore( - (state) => [ - state.sessions, - state.currentSessionIndex, - state.selectSession, - state.removeSession, - ] - ); + const [ + sessions, + selectedIndex, + selectSession, + removeSession, + editDialogTitle, + ] = useChatStore((state) => [ + state.sessions, + state.currentSessionIndex, + state.selectSession, + state.removeSession, + state.editDialogTitle, + ]); return (
@@ -116,6 +167,7 @@ export function ChatList() { selected={i === selectedIndex} onClick={() => selectSession(i)} onDelete={() => removeSession(i)} + onEdit={(title: string) => editDialogTitle(i, title)} /> ))}
@@ -196,7 +248,7 @@ export function Chat(props: { setPromptHints(promptStore.search(text)); }, 100, - { leading: true, trailing: true } + { leading: true, trailing: true }, ); const onPromptSelect = (prompt: Prompt) => { @@ -210,7 +262,7 @@ export function Chat(props: { if (!dom) return; const paddingBottomNum: number = parseInt( window.getComputedStyle(dom).paddingBottom, - 10 + 10, ); dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum; }; @@ -300,7 +352,7 @@ export function Chat(props: { preview: true, }, ] - : [] + : [], ) .concat( userInput.length > 0 @@ -312,7 +364,7 @@ export function Chat(props: { preview: true, }, ] - : [] + : [], ); // auto scroll @@ -340,7 +392,7 @@ export function Chat(props: { const newTopic = prompt(Locale.Chat.Rename, session.topic); if (newTopic && newTopic !== session.topic) { chatStore.updateCurrentSession( - (session) => (session.topic = newTopic!) + (session) => (session.topic = newTopic!), ); } }} @@ -586,7 +638,7 @@ export function Home() { state.newSession, state.currentSessionIndex, state.removeSession, - ] + ], ); const loading = !useHasHydrated(); const [showSideBar, setShowSideBar] = useState(true); diff --git a/app/icons/edit-title.svg b/app/icons/edit-title.svg new file mode 100644 index 000000000..2d0aaa39d --- /dev/null +++ b/app/icons/edit-title.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/store/app.ts b/app/store/app.ts index 118e9ed6c..9d273a29f 100644 --- a/app/store/app.ts +++ b/app/store/app.ts @@ -186,6 +186,7 @@ interface ChatStore { removeSession: (index: number) => void; selectSession: (index: number) => void; newSession: () => void; + editDialogTitle: (index: number, title: string) => void; currentSession: () => ChatSession; onNewMessage: (message: Message) => void; onUserInput: (content: string) => Promise; @@ -266,6 +267,17 @@ export const useChatStore = create()( }); }, + editDialogTitle(index: number, title: string) { + set((state) => { + const sessions = state.sessions; + sessions[index].topic = title; + + return { + sessions, + }; + }); + }, + newSession() { set((state) => ({ currentSessionIndex: 0,