Local fallbacks were creating fake saves and resurrecting deleted rows. Pin and archive now live on chat_sessions so they follow the account. Co-authored-by: Cursor <cursoragent@cursor.com>
49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import { toast } from "sonner";
|
|
|
|
export const chatNoticeToastId = "chat-notice";
|
|
|
|
export type NoticeTone = "info" | "success" | "error";
|
|
|
|
export type ChatNoticeAction = Readonly<{
|
|
label: string;
|
|
onClick: () => void;
|
|
}>;
|
|
|
|
const ongoingNotice = /正在|请稍候|请先|联网后/;
|
|
const failedNotice = /失败|无法|不可用|未能|未找到|已写满|已被删除/;
|
|
const settledNotice = /^已|^回答已恢复/;
|
|
|
|
export function noticeTone(message: string): NoticeTone {
|
|
if (ongoingNotice.test(message)) return "info";
|
|
if (failedNotice.test(message)) return "error";
|
|
if (settledNotice.test(message)) return "success";
|
|
return "info";
|
|
}
|
|
|
|
let lastNotice = "";
|
|
|
|
export function showChatNotice(message: string, action?: ChatNoticeAction) {
|
|
if (!message.trim()) {
|
|
if (!lastNotice) return;
|
|
lastNotice = "";
|
|
toast.dismiss(chatNoticeToastId);
|
|
return;
|
|
}
|
|
if (lastNotice === message && !action) return;
|
|
lastNotice = message;
|
|
const tone = noticeTone(message);
|
|
const options = {
|
|
id: chatNoticeToastId,
|
|
...(action ? { action: { label: action.label, onClick: action.onClick }, duration: Infinity } : {}),
|
|
};
|
|
if (tone === "success") {
|
|
toast.success(message, options);
|
|
return;
|
|
}
|
|
if (tone === "error") {
|
|
toast.error(message, options);
|
|
return;
|
|
}
|
|
toast(message, options);
|
|
}
|