aboutsummaryrefslogtreecommitdiffstats
path: root/renderer/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'renderer/src/components')
-rw-r--r--renderer/src/components/Header.tsx23
-rw-r--r--renderer/src/components/SettingsPage.tsx17
-rw-r--r--renderer/src/components/settings/GitSettings.tsx78
3 files changed, 113 insertions, 5 deletions
diff --git a/renderer/src/components/Header.tsx b/renderer/src/components/Header.tsx
index 3a530d3..1d954ec 100644
--- a/renderer/src/components/Header.tsx
+++ b/renderer/src/components/Header.tsx
@@ -1,6 +1,8 @@
1import React, { useState } from "react"; 1import React, { useState, useEffect } from "react";
2import type { Project, Session, Phase } from "../types"; 2import type { Project, Session, Phase } from "../types";
3 3
4const api = window.api;
5
4type Theme = "dark" | "light"; 6type Theme = "dark" | "light";
5 7
6interface HeaderProps { 8interface HeaderProps {
@@ -86,6 +88,16 @@ export function Header({
86 setIsRenamingSession(false); 88 setIsRenamingSession(false);
87 }; 89 };
88 90
91 // ── Maximize ─────────────────────────────────────────────────
92 const [isMaximized, setIsMaximized] = useState(false);
93
94 useEffect(() => {
95 // Returns the unsubscribe function; React cleanup calls it on unmount.
96 // On macOS, clicking the native green traffic light also fires this,
97 // keeping the glyph accurate when native controls are used.
98 return api.onWindowMaximized(setIsMaximized);
99 }, []);
100
89 // ── Branch copy ────────────────────────────────────────────── 101 // ── Branch copy ──────────────────────────────────────────────
90 const [copied, setCopied] = useState(false); 102 const [copied, setCopied] = useState(false);
91 103
@@ -225,6 +237,15 @@ export function Header({
225 {theme === "dark" ? "[light]" : "[dark]"} 237 {theme === "dark" ? "[light]" : "[dark]"}
226 </button> 238 </button>
227 239
240 {/* ── Maximize toggle ── */}
241 <button
242 className="maximize-btn"
243 onClick={() => api.toggleMaximize()}
244 title={isMaximized ? "Restore window" : "Maximize window"}
245 >
246 {isMaximized ? '⊡' : '□'}
247 </button>
248
228 {/* ── Settings button ── */} 249 {/* ── Settings button ── */}
229 <button className="settings-btn" onClick={onOpenSettings} title="Settings"> 250 <button className="settings-btn" onClick={onOpenSettings} title="Settings">
230 &#9881; 251 &#9881;
diff --git a/renderer/src/components/SettingsPage.tsx b/renderer/src/components/SettingsPage.tsx
index 5267665..9ebde44 100644
--- a/renderer/src/components/SettingsPage.tsx
+++ b/renderer/src/components/SettingsPage.tsx
@@ -1,7 +1,8 @@
1import React, { useState } from "react"; 1import React, { useState } from "react";
2import { SystemPromptsSettings } from "./settings/SystemPromptsSettings"; 2import { SystemPromptsSettings } from "./settings/SystemPromptsSettings";
3import { GitSettings } from "./settings/GitSettings";
3 4
4type SettingsSection = "system-prompts"; 5type SettingsSection = "system-prompts" | "git";
5 6
6interface SettingsPageProps { 7interface SettingsPageProps {
7 onClose: () => void; 8 onClose: () => void;
@@ -16,14 +17,14 @@ export function SettingsPage({ onClose }: SettingsPageProps) {
16 {/* Header — matches the main app header height/style */} 17 {/* Header — matches the main app header height/style */}
17 <div className="settings-header"> 18 <div className="settings-header">
18 <div className="settings-header-left"> 19 <div className="settings-header-left">
19 <span className="settings-title">\u2699 Settings</span> 20 <span className="settings-title">{'⚙'} Settings</span>
20 </div> 21 </div>
21 <button 22 <button
22 className="settings-close" 23 className="settings-close"
23 onClick={onClose} 24 onClick={onClose}
24 title="Close settings" 25 title="Close settings"
25 > 26 >
26 \u00d7 27 {'×'}
27 </button> 28 </button>
28 </div> 29 </div>
29 30
@@ -38,12 +39,20 @@ export function SettingsPage({ onClose }: SettingsPageProps) {
38 > 39 >
39 System Prompts 40 System Prompts
40 </button> 41 </button>
41 {/* Future sections added here */} 42 <button
43 className={`settings-nav-item${
44 activeSection === "git" ? " active" : ""
45 }`}
46 onClick={() => setActiveSection("git")}
47 >
48 Git
49 </button>
42 </nav> 50 </nav>
43 51
44 {/* Content */} 52 {/* Content */}
45 <div className="settings-content"> 53 <div className="settings-content">
46 {activeSection === "system-prompts" && <SystemPromptsSettings />} 54 {activeSection === "system-prompts" && <SystemPromptsSettings />}
55 {activeSection === "git" && <GitSettings />}
47 </div> 56 </div>
48 </div> 57 </div>
49 </div> 58 </div>
diff --git a/renderer/src/components/settings/GitSettings.tsx b/renderer/src/components/settings/GitSettings.tsx
new file mode 100644
index 0000000..0ec9875
--- /dev/null
+++ b/renderer/src/components/settings/GitSettings.tsx
@@ -0,0 +1,78 @@
1import React, { useState, useEffect } from "react";
2
3const api = window.api;
4
5export function GitSettings() {
6 // null = setting not yet loaded; true/false = loaded value
7 const [branchingEnabled, setBranchingEnabled] = useState<boolean | null>(null);
8 const [saveStatus, setSaveStatus] = useState<"idle" | "saved">("idle");
9
10 useEffect(() => {
11 api.getSettings(["git.branchingEnabled"]).then((settings) => {
12 // Key absent or any value other than "true" → false (opt-in default)
13 setBranchingEnabled(settings["git.branchingEnabled"] === "true");
14 });
15 }, []);
16
17 const handleToggle = async (enabled: boolean) => {
18 setBranchingEnabled(enabled);
19 if (enabled) {
20 await api.setSetting("git.branchingEnabled", "true");
21 } else {
22 await api.deleteSetting("git.branchingEnabled");
23 }
24 setSaveStatus("saved");
25 setTimeout(() => setSaveStatus("idle"), 1500);
26 };
27
28 if (branchingEnabled === null) {
29 return (
30 <div style={{ color: "var(--text-secondary)", fontSize: 12 }}>
31 Loading...
32 </div>
33 );
34 }
35
36 return (
37 <div>
38 <div className="settings-section-title">Git</div>
39 <div className="settings-section-desc">
40 Configure how Claude Flow interacts with your project's git repository
41 during the implement phase.
42 </div>
43
44 <div className="settings-toggle-row">
45 <label className="settings-toggle-label" htmlFor="git-branching-toggle">
46 <span className="settings-toggle-text">
47 <strong>Create a branch per session</strong>
48 <span className="settings-toggle-hint">
49 When enabled, Claude Flow checks out a new{" "}
50 <code>claude-flow/&lt;name&gt;-&lt;id&gt;</code> branch when
51 entering the implement phase. When disabled, commits land on
52 your current branch.
53 </span>
54 </span>
55 <span
56 className={`settings-toggle${branchingEnabled ? " on" : ""}`}
57 role="switch"
58 aria-checked={branchingEnabled}
59 id="git-branching-toggle"
60 tabIndex={0}
61 onClick={() => handleToggle(!branchingEnabled)}
62 onKeyDown={(e) => {
63 if (e.key === " " || e.key === "Enter") {
64 e.preventDefault();
65 handleToggle(!branchingEnabled);
66 }
67 }}
68 />
69 </label>
70 {saveStatus === "saved" && (
71 <span className="settings-custom-badge" style={{ color: "var(--accent)" }}>
72 saved ✓
73 </span>
74 )}
75 </div>
76 </div>
77 );
78}