返回 DeepSeek-Reasonix
SettingsRuleList.tsx
根目录 / desktop / frontend / src / components / SettingsRuleList.tsx
1 import { useRef, useState } from "react";
2 import { useProviderT as useT } from "../lib/providerSettingsLocale";
3 import { Tooltip } from "./Tooltip";
4
5 export function RuleList({
6 list,
7 rules,
8 busy,
9 onAdd,
10 onRemove,
11 }: {
12 list: string;
13 rules: string[];
14 busy: boolean;
15 onAdd: (rule: string) => Promise<boolean>;
16 onRemove: (rule: string) => Promise<unknown>;
17 }) {
18 const t = useT();
19 const [draft, setDraft] = useState("");
20 const adding = useRef(false);
21 const add = async () => {
22 const r = draft.trim();
23 if (!r || busy || adding.current) return;
24 adding.current = true;
25 try {
26 if (await onAdd(r)) setDraft(current => current.trim() === r ? "" : current);
27 } finally {
28 adding.current = false;
29 }
30 };
31 return (
32 <div className="set-rules">
33 <div className="set-rules__head">
34 <div className="set-rules__label">{ruleListLabel(list, t)}</div>
35 {ruleListHint(list, t) && <div className="set-rules__hint">{ruleListHint(list, t)}</div>}
36 </div>
37 <div className="set-rules__chips">
38 {rules.length === 0 && <span className="mem-empty">{t(list === "allow_write" ? "settings.noAdditionalDirectories" : "common.none")}</span>}
39 {rules.map((r) => (
40 <span className="set-rule" key={r}>
41 <span className="set-rule__text" title={r}>{r}</span>
42 <Tooltip label={t("common.delete")}>
43 <button className="set-rule__x" aria-label={`${t("common.delete")} ${r}`} disabled={busy} onClick={() => void onRemove(r)}>
44 ✕
45 </button>
46 </Tooltip>
47 </span>
48 ))}
49 </div>
50 <div className="set-rules__add">
51 <input
52 className="mem-input"
53 placeholder={list === "allow_write" ? t("settings.addWriteDirectory") : t("settings.addRule", { list })}
54 aria-label={ruleListLabel(list, t)}
55 value={draft}
56 disabled={busy}
57 onChange={(e) => setDraft(e.target.value)}
58 onKeyDown={(e) => {
59 if (e.key === "Enter" && !e.nativeEvent.isComposing) { e.preventDefault(); void add(); }
60 }}
61 />
62 <button className="btn btn--small" disabled={busy || !draft.trim()} onClick={() => void add()}>
63 {t("common.add")}
64 </button>
65 </div>
66 </div>
67 );
68 }
69
70 function ruleListLabel(list: string, t: ReturnType<typeof useT>): string {
71 switch (list) {
72 case "deny":
73 return t("settings.ruleDeny");
74 case "ask":
75 return t("settings.ruleAsk");
76 case "allow":
77 return t("settings.ruleAllow");
78 case "allow_write":
79 return t("settings.ruleAllowWrite");
80 default:
81 return list;
82 }
83 }
84
85 function ruleListHint(list: string, t: ReturnType<typeof useT>): string {
86 switch (list) {
87 case "deny":
88 return t("settings.ruleDenyHint");
89 case "ask":
90 return t("settings.ruleAskHint");
91 case "allow":
92 return t("settings.ruleAllowHint");
93 default:
94 return "";
95 }
96 }
97
97 lines Plain Text