**Layout refactor (Phase 1):** - UnifiedTopBar replacing Header.tsx — chat title editing, project folder, commit/push split button, Git branch+dirty badge, terminal/file-tree toggles - PanelZone renders FileTree, GitPanel, PreviewPanel side-by-side on the right - Independent panel toggle states in PanelContext - ResizeHandle unified across all panels - Removed old RightPanel, Header, DocPreview components **Git backend (Phase 2):** - src/lib/git/service.ts — execFile-based Git operations with timeout + injection safety - API routes: status, branches, checkout, log, commit, push, commit-detail, worktrees, derive - Worktree derive creates DB session inheriting source session settings **Git frontend (Phase 3):** - GitPanel with 4 collapsible sections: Status, Branches, History, Worktrees - CommitDialog with commit vs commit-and-push modes - GitBranchSelector with inline error, worktree-occupied branches disabled - GitWorktreeSection with switch-to/derive actions, current/dirty indicators - useGitStatus polled in AppShell, derived into context (no redundant setState) **Terminal (Phase 4):** - electron/terminal-manager.ts — child_process.spawn fallback (PTY upgrade documented) - IPC handlers + TerminalDrawer/TerminalInstance components **Polish (Phase 5):** - Push inline feedback with 4s auto-dismiss - Branch detection fix, commit diff exit-code handling - Removed redundant git state: currentBranch/gitDirtyCount now derived, not setState - useTerminal isElectron uses lazy initializer instead of effect - i18n keys (en + zh), user tutorial docs, handover document Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
32 lines
949 B
TypeScript
32 lines
949 B
TypeScript
"use client";
|
|
|
|
import { useState, useCallback } from "react";
|
|
import type { GitLogEntry } from "@/types";
|
|
|
|
export function useGitLog(cwd: string) {
|
|
const [entries, setEntries] = useState<GitLogEntry[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const fetch_ = useCallback(async (limit = 50) => {
|
|
if (!cwd) return;
|
|
setLoading(true);
|
|
setError(null);
|
|
try {
|
|
const res = await fetch(`/api/git/log?cwd=${encodeURIComponent(cwd)}&limit=${limit}`);
|
|
if (!res.ok) {
|
|
const data = await res.json();
|
|
throw new Error(data.error || 'Failed to fetch log');
|
|
}
|
|
const data = await res.json();
|
|
setEntries(data.entries);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Failed to fetch log');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [cwd]);
|
|
|
|
return { entries, loading, error, fetch: fetch_ };
|
|
}
|