aboutsummaryrefslogtreecommitdiffstats
path: root/renderer/src/components/settings
diff options
context:
space:
mode:
Diffstat (limited to 'renderer/src/components/settings')
-rw-r--r--renderer/src/components/settings/ModelSettings.tsx94
1 files changed, 94 insertions, 0 deletions
diff --git a/renderer/src/components/settings/ModelSettings.tsx b/renderer/src/components/settings/ModelSettings.tsx
new file mode 100644
index 0000000..ecfc12c
--- /dev/null
+++ b/renderer/src/components/settings/ModelSettings.tsx
@@ -0,0 +1,94 @@
1import React, { useState, useEffect } from "react";
2
3const api = window.api;
4
5export function ModelSettings() {
6 // null = not yet loaded from DB
7 const [model, setModel] = useState<string | null>(null);
8 const [draft, setDraft] = useState("");
9 const [saveStatus, setSaveStatus] = useState<"idle" | "saved">("idle");
10
11 useEffect(() => {
12 api.getSettings(["model"]).then((settings) => {
13 const saved = settings["model"] ?? "";
14 setModel(saved);
15 setDraft(saved);
16 });
17 }, []);
18
19 const handleSave = async () => {
20 const trimmed = draft.trim();
21 if (trimmed) {
22 await api.setSetting("model", trimmed);
23 setModel(trimmed);
24 } else {
25 await api.deleteSetting("model");
26 setModel("");
27 }
28 setSaveStatus("saved");
29 setTimeout(() => setSaveStatus("idle"), 1500);
30 };
31
32 const handleReset = async () => {
33 await api.deleteSetting("model");
34 setModel("");
35 setDraft("");
36 setSaveStatus("saved");
37 setTimeout(() => setSaveStatus("idle"), 1500);
38 };
39
40 if (model === null) {
41 return (
42 <div style={{ color: "var(--text-secondary)", fontSize: 12 }}>
43 Loading...
44 </div>
45 );
46 }
47
48 const isDirty = draft.trim() !== model;
49
50 return (
51 <div>
52 <div className="settings-section-title">Model</div>
53 <div className="settings-section-desc">
54 Claude model to use for all phases. Leave blank to use the SDK&apos;s
55 default model. Takes effect on the next message sent in any session.
56 </div>
57
58 <div className="settings-toggle-row">
59 <input
60 className="settings-model-input"
61 type="text"
62 value={draft}
63 placeholder="Default (e.g. claude-sonnet-4-5)"
64 onChange={(e) => {
65 setDraft(e.target.value);
66 setSaveStatus("idle");
67 }}
68 onKeyDown={(e) => {
69 if (e.key === "Enter") handleSave();
70 }}
71 spellCheck={false}
72 />
73 </div>
74
75 <div className="settings-actions">
76 {model && (
77 <button className="btn-secondary" onClick={handleReset}>
78 Reset to Default
79 </button>
80 )}
81 <button
82 className="btn-primary"
83 onClick={handleSave}
84 disabled={!isDirty}
85 >
86 {saveStatus === "saved" ? "Saved \u2713" : "Save"}
87 </button>
88 {model && (
89 <span className="settings-custom-badge">custom</span>
90 )}
91 </div>
92 </div>
93 );
94}