修复 AI 历史会话删除在 App 内无响应的问题
WebView 不支持 window.confirm,改用 AlertDialog 显示删除确认框。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+61
-22
@@ -8,6 +8,16 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
import BottomNav from "@/components/BottomNav";
|
import BottomNav from "@/components/BottomNav";
|
||||||
import ConnectionPlaceholder from "@/components/ConnectionPlaceholder";
|
import ConnectionPlaceholder from "@/components/ConnectionPlaceholder";
|
||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogAction,
|
||||||
|
AlertDialogCancel,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogTitle,
|
||||||
|
} from "@/components/ui/alert-dialog";
|
||||||
import { useDevice } from "@/contexts/DeviceContext";
|
import { useDevice } from "@/contexts/DeviceContext";
|
||||||
import {
|
import {
|
||||||
AI_SPLIT_RESTORE_PATH_KEY,
|
AI_SPLIT_RESTORE_PATH_KEY,
|
||||||
@@ -211,6 +221,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
|
|||||||
const deviceName = deviceState?.device ?? "Luxsin X9";
|
const deviceName = deviceState?.device ?? "Luxsin X9";
|
||||||
|
|
||||||
const aiText = useMemo(() => resolveAILocale(language), [language]);
|
const aiText = useMemo(() => resolveAILocale(language), [language]);
|
||||||
|
const promptText = useMemo(() => resolveLocalePack(language).prompt, [language]);
|
||||||
|
|
||||||
const restoreDesktopSplit = useCallback(() => {
|
const restoreDesktopSplit = useCallback(() => {
|
||||||
const path = readAndClearAiSplitRestorePath();
|
const path = readAndClearAiSplitRestorePath();
|
||||||
@@ -223,6 +234,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
|
|||||||
const [input, setInput] = useState("");
|
const [input, setInput] = useState("");
|
||||||
const [sending, setSending] = useState(false);
|
const [sending, setSending] = useState(false);
|
||||||
const [historyOpen, setHistoryOpen] = useState(false);
|
const [historyOpen, setHistoryOpen] = useState(false);
|
||||||
|
const [pendingDeleteId, setPendingDeleteId] = useState<string | null>(null);
|
||||||
const [chats, setChats] = useState<ChatRead[]>([]);
|
const [chats, setChats] = useState<ChatRead[]>([]);
|
||||||
// 初次加载历史会话期间,避免先闪一下欢迎页再切到消息
|
// 初次加载历史会话期间,避免先闪一下欢迎页再切到消息
|
||||||
const [initializing, setInitializing] = useState(true);
|
const [initializing, setInitializing] = useState(true);
|
||||||
@@ -382,27 +394,22 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
|
|||||||
}
|
}
|
||||||
}, [aiText, chatId, newChat]);
|
}, [aiText, chatId, newChat]);
|
||||||
|
|
||||||
// ── 历史面板里删除某条会话 ──
|
// ── 历史面板里删除某条会话(确认框用 AlertDialog,WebView 不支持 window.confirm) ──
|
||||||
const deleteChatById = useCallback(
|
const confirmDeleteChat = useCallback(async (id: string) => {
|
||||||
async (id: string) => {
|
try {
|
||||||
const ok = window.confirm(aiText.history.deleteConfirm);
|
await clearChat(id);
|
||||||
if (!ok) return;
|
setChats((prev) => prev.filter((c) => c.id !== id));
|
||||||
try {
|
if (chatId === id) {
|
||||||
await clearChat(id);
|
setChatId(null);
|
||||||
setChats((prev) => prev.filter((c) => c.id !== id));
|
setMessages([]);
|
||||||
if (chatId === id) {
|
|
||||||
setChatId(null);
|
|
||||||
setMessages([]);
|
|
||||||
}
|
|
||||||
toast.success(aiText.history.deleted);
|
|
||||||
} catch (e: any) {
|
|
||||||
toast.error(
|
|
||||||
formatText(aiText.history.deleteFailed, { message: e?.message ?? e }),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
toast.success(aiText.history.deleted);
|
||||||
[aiText, chatId],
|
} catch (e: any) {
|
||||||
);
|
toast.error(
|
||||||
|
formatText(aiText.history.deleteFailed, { message: e?.message ?? e }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [aiText, chatId]);
|
||||||
|
|
||||||
// ── 发送提问 ──
|
// ── 发送提问 ──
|
||||||
const send = useCallback(
|
const send = useCallback(
|
||||||
@@ -897,10 +904,41 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
|
|||||||
onClose={() => setHistoryOpen(false)}
|
onClose={() => setHistoryOpen(false)}
|
||||||
onSelect={(id) => loadChat(id)}
|
onSelect={(id) => loadChat(id)}
|
||||||
onNew={newChat}
|
onNew={newChat}
|
||||||
onDelete={deleteChatById}
|
onDelete={setPendingDeleteId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<AlertDialog
|
||||||
|
open={pendingDeleteId !== null}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
if (!open) setPendingDeleteId(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AlertDialogContent className="top-[42%] z-[70] border-white/10 bg-zinc-900 text-white sm:max-w-md">
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle className="text-white">
|
||||||
|
{aiText.history.delete}
|
||||||
|
</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription className="text-white/60">
|
||||||
|
{aiText.history.deleteConfirm}
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel className="border-white/20 bg-transparent text-white hover:bg-white/10">
|
||||||
|
{promptText.cancel}
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction
|
||||||
|
className="bg-red-500 text-white hover:bg-red-500/90 focus-visible:ring-red-500"
|
||||||
|
onClick={() => {
|
||||||
|
if (pendingDeleteId) void confirmDeleteChat(pendingDeleteId);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{promptText.delete}
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
|
||||||
{/* ── 对比对话框 ── */}
|
{/* ── 对比对话框 ── */}
|
||||||
{compareMsg && (
|
{compareMsg && (
|
||||||
<CompareDialog
|
<CompareDialog
|
||||||
@@ -1147,11 +1185,12 @@ function HistoryPanel({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onDelete(c.id);
|
onDelete(c.id);
|
||||||
}}
|
}}
|
||||||
className="ml-2 w-8 h-8 rounded-full flex items-center justify-center text-white/40 hover:text-red-400 active:text-red-500 transition-colors"
|
className="ml-2 w-8 h-8 shrink-0 rounded-full flex items-center justify-center text-white/40 hover:text-red-400 active:text-red-500 transition-colors touch-manipulation"
|
||||||
style={{ background: "rgba(44,44,46,0.6)" }}
|
style={{ background: "rgba(44,44,46,0.6)" }}
|
||||||
aria-label={aiText.history.delete}
|
aria-label={aiText.history.delete}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user