From e8467fca929df480bf43283b2dce0e58d1857bdc Mon Sep 17 00:00:00 2001 From: Your Name <you@example.com> Date: Sat, 3 Feb 2024 22:38:06 -0600 Subject: [PATCH] update: we can change the chat title for each session following the Chatgpt --- src/App.tsx | 22 ++++++++ src/components/Sidebar.tsx | 100 +++++++++++++++++++++++++++++++++---- src/store/sessions.tsx | 1 + 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a880483..b7ad283 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -70,6 +70,26 @@ const App = () => { } }; + const onRenameSession = (id: string, newTitle: string) => { + let confirmStr = "确定要更新主题名称变更为 " + newTitle + " 吗? "; + const _sessions = { + ...sessions, + [id]: [ + { + ...sessions[id][0], + title: newTitle + }, + ...sessions[id].slice(1) + ], + }; + + sendUserConfirm(confirmStr, () => { + dispatch(updateSessions(_sessions)); + sendUserAlert("对话记录已更新"); + }); + + }; + const handleDeleteSession = (id: string) => { sendUserConfirm("确定要删除这条对话记录吗?", () => { navigate(routes.index.prefix); @@ -138,6 +158,7 @@ const App = () => { { role: "user", parts: prompt, + title: prompt.slice(0, 20), timestamp: currentTimestamp, attachment: uploadInlineData, }, @@ -221,6 +242,7 @@ const App = () => { newChatUrl={routes.index.prefix} onExportSession={handleExportSession} onDeleteSession={handleDeleteSession} + onRenameSession={onRenameSession} /> <Container ref={mainSectionRef} diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 1e03238..9587302 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,5 +1,7 @@ import exportIcon from "../assets/icons/file-export-solid.svg"; import deleteIcon from "../assets/icons/trash-can-solid.svg"; +import renameIcon from "../assets/icons/pen-to-square-solid.svg"; + import historyIcon from "../assets/icons/clock-rotate-left-solid.svg"; import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; @@ -13,6 +15,7 @@ interface SidebarProps { readonly sessions: Sessions; readonly onDeleteSession?: (id: string) => void; readonly onExportSession?: (id: string) => void; + readonly onRenameSession?: (id: string, newTitle: string) => void; } export const Sidebar = (props: SidebarProps) => { @@ -24,8 +27,12 @@ export const Sidebar = (props: SidebarProps) => { sessions, onDeleteSession, onExportSession, + onRenameSession, } = props; + const [editingId, setEditingId] = useState("") + const [chatTitle, setChatTitle] = useState("") + const [sessionsLimitation, setSessionsLimitation] = useState( limitation || 10 ); @@ -115,8 +122,35 @@ export const Sidebar = (props: SidebarProps) => { className="flex-1 text-sm text-left truncate" to={`/chat/${item}`} > - {sessionsCategory.today[item][0].parts} + + {sessionsCategory.today[item][0].title? sessionsCategory.today[item][0].title : sessionsCategory.today[item][0].parts} </Link> + {editingId == item ? ( + <input + autoFocus={true} + className="flex=1 min-w-0 bg-transparent outline-none" + value={chatTitle} + onChange={(e) => { + setChatTitle(e.target.value) + }} + onBlur={(e)=>{ + onRenameSession && + onRenameSession(item, e.target.value) + setEditingId("") + }} + + />) :( + <img + className="cursor-pointer text-xs size-3 hover:scale-125 transition-all" + src={renameIcon} + alt="Rename" + onClick={() => { + setEditingId(item) + setChatTitle(String(sessionsCategory.today[item][0].title? sessionsCategory.today[item][0].title : sessionsCategory.today[item][0].parts)) + } + + } + />)} <img className="cursor-pointer text-xs size-3 hover:scale-125 transition-all" src={exportIcon} @@ -152,11 +186,35 @@ export const Sidebar = (props: SidebarProps) => { className="flex-1 text-sm text-left truncate" to={`/chat/${item}`} > - { - sessionsCategory.yesterday[item][0] - .parts - } + + {sessionsCategory.yesterday[item][0].title? sessionsCategory.yesterday[item][0].title : sessionsCategory.yesterday[item][0].parts} </Link> + {editingId == item ? ( + <input + autoFocus={true} + className="flex=1 min-w-0 bg-transparent outline-none" + value={chatTitle} + onChange={(e) => { + setChatTitle(e.target.value) + }} + onBlur={(e)=>{ + onRenameSession && + onRenameSession(item, e.target.value) + setEditingId("") + }} + + />) :( + <img + className="cursor-pointer text-xs size-3 hover:scale-125 transition-all" + src={renameIcon} + alt="Rename" + onClick={() => { + setEditingId(item) + setChatTitle(String(sessionsCategory.yesterday[item][0].title? sessionsCategory.yesterday[item][0].title : sessionsCategory.yesterday[item][0].parts)) + } + + } + />)} <img className="cursor-pointer text-xs size-3 hover:scale-125 transition-all" src={exportIcon} @@ -194,12 +252,34 @@ export const Sidebar = (props: SidebarProps) => { className="flex-1 text-sm text-left truncate" to={`/chat/${item}`} > - { - sessionsCategory.earlier[ - item - ][0].parts - } + {sessionsCategory.earlier[item][0].title? sessionsCategory.earlier[item][0].title : sessionsCategory.earlier[item][0].parts} </Link> + {editingId == item ? ( + <input + autoFocus={true} + className="flex=1 min-w-0 bg-transparent outline-none" + value={chatTitle} + onChange={(e) => { + setChatTitle(e.target.value) + }} + onBlur={(e)=>{ + onRenameSession && + onRenameSession(item, e.target.value) + setEditingId("") + }} + + />) :( + <img + className="cursor-pointer text-xs size-3 hover:scale-125 transition-all" + src={renameIcon} + alt="Rename" + onClick={() => { + setEditingId(item) + setChatTitle(String(sessionsCategory.yesterday[item][0].title? sessionsCategory.yesterday[item][0].title : sessionsCategory.yesterday[item][0].parts)) + } + + } + />)} <img className="cursor-pointer text-xs size-3 hover:scale-125 transition-all" src={exportIcon} diff --git a/src/store/sessions.tsx b/src/store/sessions.tsx index 175641d..d627464 100644 --- a/src/store/sessions.tsx +++ b/src/store/sessions.tsx @@ -6,6 +6,7 @@ export interface SessionHistory { readonly parts: string; readonly timestamp: number; readonly attachment?: GenerativeContentBlob; + readonly title?: string; } export type Sessions = Record<string, SessionHistory[]>; export const initialSessions: Sessions = {};