Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { toast } from "sonner";
|
|
import { NOTICE_DURATION_MS } from "./notify.ts";
|
|
|
|
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,
|
|
duration: NOTICE_DURATION_MS[tone],
|
|
...(tone === "error" ? { closeButton: true } : {}),
|
|
...(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);
|
|
}
|