feat: support for renaming topics(title) #112

This commit is contained in:
AprilNEA 2023-03-29 15:42:39 +08:00
parent 067121d968
commit b0e7cb4eff
No known key found for this signature in database
GPG Key ID: B93E17BB436B4DE1
2 changed files with 66 additions and 31 deletions

View File

@ -1,6 +1,12 @@
"use client"; "use client";
import { useState, useRef, useEffect, useLayoutEffect } from "react"; import {
useState,
useRef,
useEffect,
useLayoutEffect,
ChangeEvent,
} from "react";
import { useDebouncedCallback } from "use-debounce"; import { useDebouncedCallback } from "use-debounce";
import { IconButton } from "./button"; import { IconButton } from "./button";
@ -74,6 +80,16 @@ export function ChatItem(props: {
time: string; time: string;
selected: boolean; selected: boolean;
}) { }) {
const [updateTitle] = useChatStore((state) => [state.updateTitle]);
const [title, setTitle] = useState(props.title);
const [isEditing, setIsEditing] = useState(false);
const handleInputBlur = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.value.length == 0) setTitle(props.title);
setIsEditing(false);
updateTitle(e.target.value);
};
return ( return (
<div <div
className={`${styles["chat-item"]} ${ className={`${styles["chat-item"]} ${
@ -81,7 +97,20 @@ export function ChatItem(props: {
}`} }`}
onClick={props.onClick} onClick={props.onClick}
> >
<div className={styles["chat-item-title"]}>{props.title}</div> <div
className={styles["chat-item-title"]}
onDoubleClick={() => setIsEditing(true)}
>
{isEditing ? (
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
onBlur={handleInputBlur}
/>
) : (
title
)}
</div>
<div className={styles["chat-item-info"]}> <div className={styles["chat-item-info"]}>
<div className={styles["chat-item-count"]}> <div className={styles["chat-item-count"]}>
{Locale.ChatItem.ChatItemCount(props.count)} {Locale.ChatItem.ChatItemCount(props.count)}
@ -102,7 +131,7 @@ export function ChatList() {
state.currentSessionIndex, state.currentSessionIndex,
state.selectSession, state.selectSession,
state.removeSession, state.removeSession,
] ],
); );
return ( return (
@ -194,7 +223,7 @@ export function Chat(props: { showSideBar?: () => void }) {
setPromptHints(promptStore.search(text)); setPromptHints(promptStore.search(text));
}, },
100, 100,
{ leading: true, trailing: true } { leading: true, trailing: true },
); );
const onPromptSelect = (prompt: Prompt) => { const onPromptSelect = (prompt: Prompt) => {
@ -280,7 +309,7 @@ export function Chat(props: { showSideBar?: () => void }) {
preview: true, preview: true,
}, },
] ]
: [] : [],
) )
.concat( .concat(
userInput.length > 0 userInput.length > 0
@ -292,7 +321,7 @@ export function Chat(props: { showSideBar?: () => void }) {
preview: true, preview: true,
}, },
] ]
: [] : [],
); );
// auto scroll // auto scroll
@ -375,32 +404,33 @@ export function Chat(props: { showSideBar?: () => void }) {
</div> </div>
)} )}
<div className={styles["chat-message-item"]}> <div className={styles["chat-message-item"]}>
{(!isUser && !(message.preview || message.content.length === 0)) && ( {!isUser &&
<div className={styles["chat-message-top-actions"]}> !(message.preview || message.content.length === 0) && (
{message.streaming ? ( <div className={styles["chat-message-top-actions"]}>
<div {message.streaming ? (
className={styles["chat-message-top-action"]} <div
onClick={() => onUserStop(i)} className={styles["chat-message-top-action"]}
> onClick={() => onUserStop(i)}
{Locale.Chat.Actions.Stop} >
</div> {Locale.Chat.Actions.Stop}
) : ( </div>
<div ) : (
className={styles["chat-message-top-action"]} <div
onClick={() => onResend(i)} className={styles["chat-message-top-action"]}
> onClick={() => onResend(i)}
{Locale.Chat.Actions.Retry} >
</div> {Locale.Chat.Actions.Retry}
)} </div>
)}
<div <div
className={styles["chat-message-top-action"]} className={styles["chat-message-top-action"]}
onClick={() => copyToClipboard(message.content)} onClick={() => copyToClipboard(message.content)}
> >
{Locale.Chat.Actions.Copy} {Locale.Chat.Actions.Copy}
</div>
</div> </div>
</div> )}
)}
{(message.preview || message.content.length === 0) && {(message.preview || message.content.length === 0) &&
!isUser ? ( !isUser ? (
<LoadingIcon /> <LoadingIcon />
@ -555,7 +585,7 @@ export function Home() {
state.newSession, state.newSession,
state.currentSessionIndex, state.currentSessionIndex,
state.removeSession, state.removeSession,
] ],
); );
const loading = !useHasHydrated(); const loading = !useHasHydrated();
const [showSideBar, setShowSideBar] = useState(true); const [showSideBar, setShowSideBar] = useState(true);

View File

@ -192,6 +192,7 @@ interface ChatStore {
summarizeSession: () => void; summarizeSession: () => void;
updateStat: (message: Message) => void; updateStat: (message: Message) => void;
updateCurrentSession: (updater: (session: ChatSession) => void) => void; updateCurrentSession: (updater: (session: ChatSession) => void) => void;
updateTitle: (title: string) => void;
updateMessage: ( updateMessage: (
sessionIndex: number, sessionIndex: number,
messageIndex: number, messageIndex: number,
@ -390,6 +391,10 @@ export const useChatStore = create<ChatStore>()(
set(() => ({ sessions })); set(() => ({ sessions }));
}, },
updateTitle(title: string) {
get().updateCurrentSession((session) => (session.topic = title));
},
summarizeSession() { summarizeSession() {
const session = get().currentSession(); const session = get().currentSession();