From 0484d97dfbc3b8a2e7878d3ab35a9895decdf467 Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 28 Feb 2026 21:35:39 -0800 Subject: feat: **1 — `git.ts`:** Add exported `getCurrentBranch` helpe… (+8 more) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ✅ **1 — `git.ts`:** Add exported `getCurrentBranch` helper after `ensureGitRepo` - ✅ **2a — `ipc/handlers.ts`:** Update git import to include `ensureGitRepo` and `getCurrentBranch` - ✅ **2b — `ipc/handlers.ts`:** Replace `workflow:advance` implement-phase block with branching-toggle logic - ✅ **3 — `GitSettings.tsx`:** Create new settings component with pill toggle - ✅ **4 — `SettingsPage.tsx`:** Add `"git"` section type, import, nav item, content render; fix both unicode glyphs - ✅ **5 — `globals.css`:** Append toggle-row + pill toggle + maximize-btn CSS - ✅ **6 — `index.ts`:** Add `ipcMain` to import; add `window:toggleMaximize` handler + maximize/unmaximize events inside `createWindow()` - ✅ **7 — `preload.ts`:** Add `toggleMaximize` + `onWindowMaximized` to interface and `api` object - ✅ **8 — `Header.tsx`:** Add `isMaximized` state + effect + maximize button in JSX --- src/main/git.ts | 23 +++++++++++++++++++++++ src/main/index.ts | 14 +++++++++++++- src/main/ipc/handlers.ts | 27 ++++++++++++++++++++++----- src/main/preload.ts | 12 ++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) (limited to 'src/main') diff --git a/src/main/git.ts b/src/main/git.ts index 20362a7..ec81e8f 100644 --- a/src/main/git.ts +++ b/src/main/git.ts @@ -57,6 +57,29 @@ export function ensureGitRepo(projectPath: string): void { } } +// --------------------------------------------------------------------------- +// Current branch query +// --------------------------------------------------------------------------- + +/** + * Returns the name of the currently checked-out branch, + * or null if git is unavailable or HEAD is detached. + */ +export function getCurrentBranch(projectPath: string): string | null { + try { + return ( + execFileSync("git", ["branch", "--show-current"], { + cwd: projectPath, + stdio: "pipe", + }) + .toString() + .trim() || null + ); + } catch { + return null; + } +} + // --------------------------------------------------------------------------- // Branch creation // --------------------------------------------------------------------------- diff --git a/src/main/index.ts b/src/main/index.ts index a7bed00..f913ac0 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow, Menu } from "electron"; +import { app, BrowserWindow, Menu, ipcMain } from "electron"; import path from "node:path"; import { getDb, closeDb } from "./db"; import { registerIpcHandlers } from "./ipc/handlers"; @@ -23,6 +23,18 @@ function createWindow() { registerIpcHandlers(mainWindow); + // Maximize toggle — works identically on Linux and macOS + ipcMain.handle("window:toggleMaximize", () => { + if (mainWindow!.isMaximized()) mainWindow!.unmaximize(); + else mainWindow!.maximize(); + }); + + // Push state to renderer so the button glyph stays accurate. + // On macOS, clicking the green traffic light also fires these events, + // keeping our custom button in sync with the native control. + mainWindow.on("maximize", () => mainWindow!.webContents.send("window:maximized", true)); + mainWindow.on("unmaximize", () => mainWindow!.webContents.send("window:maximized", false)); + if (isDev) { const url = process.env.VITE_DEV_SERVER_URL ?? "http://localhost:5173"; mainWindow.loadURL(url).finally(() => { diff --git a/src/main/ipc/handlers.ts b/src/main/ipc/handlers.ts index bc7d78d..e0863f3 100644 --- a/src/main/ipc/handlers.ts +++ b/src/main/ipc/handlers.ts @@ -3,7 +3,7 @@ import * as projects from "../db/projects"; import * as sessions from "../db/sessions"; import * as claude from "../claude"; import * as settingsDb from "../db/settings"; -import { createSessionBranch, ensureGitIgnore } from "../git"; +import { createSessionBranch, ensureGitIgnore, ensureGitRepo, getCurrentBranch } from "../git"; import type { UserPermissionMode } from "../claude/phases"; import { getDefaultSystemPromptTemplate } from "../claude/phases"; @@ -113,10 +113,27 @@ export function registerIpcHandlers(mainWindow: BrowserWindow): void { if (nextPhase === "implement") { const project = projects.getProject(session.project_id); if (project) { - const branchName = createSessionBranch(project.path, session.name, session.id); - if (branchName) { - sessions.updateSession(sessionId, { git_branch: branchName }); - git_branch = branchName; + const branchingSetting = settingsDb.getSetting("git.branchingEnabled"); + const branchingEnabled = branchingSetting === "true"; // opt-in; default = off + + // Always ensure repo + gitignore so commits work regardless of mode + try { ensureGitIgnore(project.path); } catch { /* non-fatal */ } + try { ensureGitRepo(project.path); } catch { /* non-fatal */ } + + if (branchingEnabled) { + // createSessionBranch internally calls ensureGitIgnore/ensureGitRepo again + // (belt-and-suspenders), then checks out a new claude-flow/- branch + const branchName = createSessionBranch(project.path, session.name, session.id); + if (branchName) { + sessions.updateSession(sessionId, { git_branch: branchName }); + git_branch = branchName; + } + } else { + // No new branch — commit to whatever branch is currently checked out. + // Store the branch name so autoCommitTurn's boolean guard passes. + const currentBranch = getCurrentBranch(project.path) ?? "main"; + sessions.updateSession(sessionId, { git_branch: currentBranch }); + git_branch = currentBranch; } } } diff --git a/src/main/preload.ts b/src/main/preload.ts index 52e947b..44467db 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -62,6 +62,10 @@ export interface ClaudeFlowAPI { // Dialogs selectDirectory: () => Promise; + + // Window + toggleMaximize: () => Promise; + onWindowMaximized: (cb: (isMaximized: boolean) => void) => () => void; } const api: ClaudeFlowAPI = { @@ -127,6 +131,14 @@ const api: ClaudeFlowAPI = { const result = await ipcRenderer.invoke("dialog:selectDirectory"); return result; }, + + // Window + toggleMaximize: () => ipcRenderer.invoke("window:toggleMaximize"), + onWindowMaximized: (cb) => { + const handler = (_: IpcRendererEvent, val: boolean) => cb(val); + ipcRenderer.on("window:maximized", handler); + return () => ipcRenderer.removeListener("window:maximized", handler); + }, }; contextBridge.exposeInMainWorld("api", api); -- cgit v1.2.3