feat: #499 revert delete session

This commit is contained in:
Yidadaa 2023-04-07 00:14:27 +08:00
parent 806587c8ea
commit 5952064362
11 changed files with 80 additions and 17 deletions

View File

@ -12,7 +12,7 @@
user-select: none;
outline: none;
border: none;
color: rgb(51, 51, 51);
color: var(--black);
&[disabled] {
cursor: not-allowed;

View File

@ -59,6 +59,7 @@ export function ChatList() {
state.removeSession,
state.moveSession,
]);
const chatStore = useChatStore();
const onDragEnd: OnDragEndResponder = (result) => {
const { destination, source } = result;
@ -95,10 +96,7 @@ export function ChatList() {
index={i}
selected={i === selectedIndex}
onClick={() => selectSession(i)}
onDelete={() =>
(!isMobileScreen() || confirm(Locale.Home.DeleteChat)) &&
removeSession(i)
}
onDelete={chatStore.deleteSession}
/>
))}
{provided.placeholder}

View File

@ -93,6 +93,7 @@ function _Home() {
state.removeSession,
],
);
const chatStore = useChatStore();
const loading = !useHasHydrated();
const [showSideBar, setShowSideBar] = useState(true);
@ -142,11 +143,7 @@ function _Home() {
<div className={styles["sidebar-action"] + " " + styles.mobile}>
<IconButton
icon={<CloseIcon />}
onClick={() => {
if (confirm(Locale.Home.DeleteChat)) {
removeSession(currentIndex);
}
}}
onClick={chatStore.deleteSession}
/>
</div>
<div className={styles["sidebar-action"]}>

View File

@ -135,9 +135,25 @@
box-shadow: var(--card-shadow);
border: var(--border-in-light);
color: var(--black);
padding: 10px 30px;
padding: 10px 20px;
border-radius: 50px;
margin-bottom: 20px;
display: flex;
align-items: center;
.toast-action {
padding-left: 20px;
color: var(--primary);
opacity: 0.8;
border: 0;
background: none;
cursor: pointer;
font-family: inherit;
&:hover {
opacity: 1;
}
}
}
}
@ -160,4 +176,4 @@
max-height: 50vh;
}
}
}
}

View File

@ -110,17 +110,37 @@ export function showModal(props: ModalProps) {
root.render(<Modal {...props} onClose={closeModal}></Modal>);
}
export type ToastProps = { content: string };
export type ToastProps = {
content: string;
action?: {
text: string;
onClick: () => void;
};
};
export function Toast(props: ToastProps) {
return (
<div className={styles["toast-container"]}>
<div className={styles["toast-content"]}>{props.content}</div>
<div className={styles["toast-content"]}>
<span>{props.content}</span>
{props.action && (
<button
onClick={props.action.onClick}
className={styles["toast-action"]}
>
{props.action.text}
</button>
)}
</div>
</div>
);
}
export function showToast(content: string, delay = 3000) {
export function showToast(
content: string,
action?: ToastProps["action"],
delay = 3000,
) {
const div = document.createElement("div");
div.className = styles.show;
document.body.appendChild(div);
@ -139,7 +159,7 @@ export function showToast(content: string, delay = 3000) {
close();
}, delay);
root.render(<Toast content={content} />);
root.render(<Toast content={content} action={action} />);
}
export type InputProps = React.HTMLProps<HTMLTextAreaElement> & {

View File

@ -47,6 +47,8 @@ const cn = {
Home: {
NewChat: "新的聊天",
DeleteChat: "确认删除选中的对话?",
DeleteToast: "已删除会话",
Revert: "撤销",
},
Settings: {
Title: "设置",

View File

@ -50,6 +50,8 @@ const en: LocaleType = {
Home: {
NewChat: "New Chat",
DeleteChat: "Confirm to delete the selected conversation?",
DeleteToast: "Chat Deleted",
Revert: "Revert",
},
Settings: {
Title: "Settings",

View File

@ -50,6 +50,8 @@ const es: LocaleType = {
Home: {
NewChat: "Nuevo chat",
DeleteChat: "¿Confirmar eliminación de la conversación seleccionada?",
DeleteToast: "Chat Deleted",
Revert: "Revert",
},
Settings: {
Title: "Configuración",

View File

@ -50,6 +50,8 @@ const it: LocaleType = {
Home: {
NewChat: "Nuova Chat",
DeleteChat: "Confermare la cancellazione della conversazione selezionata?",
DeleteToast: "Chat Deleted",
Revert: "Revert",
},
Settings: {
Title: "Impostazioni",

View File

@ -48,6 +48,8 @@ const tw: LocaleType = {
Home: {
NewChat: "新的對話",
DeleteChat: "確定要刪除選取的對話嗎?",
DeleteToast: "已刪除對話",
Revert: "撤銷",
},
Settings: {
Title: "設定",

View File

@ -7,9 +7,10 @@ import {
requestChatStream,
requestWithPrompt,
} from "../requests";
import { trimTopic } from "../utils";
import { isMobileScreen, trimTopic } from "../utils";
import Locale from "../locales";
import { showToast } from "../components/ui-lib";
export type Message = ChatCompletionResponseMessage & {
date: string;
@ -204,6 +205,7 @@ interface ChatStore {
moveSession: (from: number, to: number) => void;
selectSession: (index: number) => void;
newSession: () => void;
deleteSession: () => void;
currentSession: () => ChatSession;
onNewMessage: (message: Message) => void;
onUserInput: (content: string) => Promise<void>;
@ -324,6 +326,26 @@ export const useChatStore = create<ChatStore>()(
}));
},
deleteSession() {
const deletedSession = get().currentSession();
const index = get().currentSessionIndex;
const isLastSession = get().sessions.length === 1;
if (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) {
get().removeSession(index);
}
showToast(Locale.Home.DeleteToast, {
text: Locale.Home.Revert,
onClick() {
set((state) => ({
sessions: state.sessions
.slice(0, index)
.concat([deletedSession])
.concat(state.sessions.slice(index + Number(isLastSession))),
}));
},
});
},
currentSession() {
let index = get().currentSessionIndex;
const sessions = get().sessions;