返回 DeepSeek-Reasonix
UndoRewindBanner.tsx
根目录 / desktop / frontend / src / components / UndoRewindBanner.tsx
1 import { useState } from "react";
2 import { useT } from "../lib/i18n";
3
4 export interface UndoRewindMeta {
5 /** How many conversation turns were lost. */
6 turns: number;
7 /** File paths that were restored (code rewind). */
8 filesRestored: string[];
9 /** File paths that were removed (code rewind). */
10 filesRemoved: string[];
11 /** Callback when the user confirms undo. */
12 onUndo: () => void;
13 }
14
15 export function UndoRewindBanner({ meta }: { meta: UndoRewindMeta }) {
16 const t = useT();
17 const [confirm, setConfirm] = useState(false);
18
19 const parts: string[] = [];
20 if (meta.turns > 0) parts.push(t("undoRewind.turns", { n: meta.turns }));
21 if (meta.filesRestored.length > 0)
22 parts.push(t("undoRewind.filesRestored", { n: meta.filesRestored.length }));
23 if (meta.filesRemoved.length > 0)
24 parts.push(t("undoRewind.filesRemoved", { n: meta.filesRemoved.length }));
25 const summary = parts.join(" · ");
26
27 const files = [...new Set([...meta.filesRestored, ...meta.filesRemoved])];
28 const fileList = files.length > 0 ? files.slice(0, 3).map((f) => f.split(/[/\\]/).pop() || f).join(", ") + (files.length > 3 ? ` +${files.length - 3}` : "") : "";
29
30 return (
31 <div className="undo-rewind">
32 <div className="undo-rewind__info">
33 <span className="undo-rewind__label">{summary}</span>
34 {fileList && <span className="undo-rewind__files">{fileList}</span>}
35 </div>
36 <button
37 type="button"
38 className={`undo-rewind__btn${confirm ? " undo-rewind__btn--confirm" : ""}`}
39 onClick={() => {
40 if (confirm) {
41 meta.onUndo();
42 setConfirm(false);
43 } else {
44 setConfirm(true);
45 }
46 }}
47 >
48 {confirm ? t("undoRewind.confirm") : t("undoRewind.undo")}
49 </button>
50 </div>
51 );
52 }
53
53 lines Plain Text