feat: enhance UI components and branch management

- Added new RadioGroup and Switch components for better UI interaction.
- Introduced BranchSelector for improved branch selection in feature dialogs.
- Updated Autocomplete and BranchAutocomplete components to handle error states.
- Refactored feature management to archive verified features instead of deleting them.
- Enhanced worktree handling by removing worktreePath from features, relying on branchName instead.
- Improved auto mode functionality by integrating branch management and worktree updates.
- Cleaned up unused code and optimized existing logic for better performance.
This commit is contained in:
Cody Seibert
2025-12-17 22:29:39 -05:00
parent cffdec91f1
commit 0549b8085a
45 changed files with 1669 additions and 1346 deletions

View File

@@ -296,9 +296,8 @@ export interface Feature {
error?: string; // Error message if the agent errored during processing
priority?: number; // Priority: 1 = high, 2 = medium, 3 = low
dependencies?: string[]; // Array of feature IDs this feature depends on
// Worktree info - set when a feature is being worked on in an isolated git worktree
worktreePath?: string; // Path to the worktree directory
branchName?: string; // Name of the feature branch
// Branch info - worktree path is derived at runtime from branchName
branchName?: string; // Name of the feature branch (undefined = use current worktree)
justFinishedAt?: string; // ISO timestamp when agent just finished and moved to waiting_approval (shows badge for 2 minutes)
}
@@ -404,7 +403,10 @@ export interface AppState {
// User-managed Worktrees (per-project)
// projectPath -> { path: worktreePath or null for main, branch: branch name }
currentWorktreeByProject: Record<string, { path: string | null; branch: string }>;
currentWorktreeByProject: Record<
string,
{ path: string | null; branch: string }
>;
worktreesByProject: Record<
string,
Array<{
@@ -588,7 +590,11 @@ export interface AppActions {
// Worktree Settings actions
setUseWorktrees: (enabled: boolean) => void;
setCurrentWorktree: (projectPath: string, worktreePath: string | null, branch: string) => void;
setCurrentWorktree: (
projectPath: string,
worktreePath: string | null,
branch: string
) => void;
setWorktrees: (
projectPath: string,
worktrees: Array<{
@@ -599,7 +605,9 @@ export interface AppActions {
changedFilesCount?: number;
}>
) => void;
getCurrentWorktree: (projectPath: string) => { path: string | null; branch: string } | null;
getCurrentWorktree: (
projectPath: string
) => { path: string | null; branch: string } | null;
getWorktrees: (projectPath: string) => Array<{
path: string;
branch: string;
@@ -607,6 +615,8 @@ export interface AppActions {
hasChanges?: boolean;
changedFilesCount?: number;
}>;
isPrimaryWorktreeBranch: (projectPath: string, branchName: string) => boolean;
getPrimaryWorktreeBranch: (projectPath: string) => string | null;
// Profile Display Settings actions
setShowProfilesOnly: (enabled: boolean) => void;
@@ -1347,7 +1357,8 @@ export const useAppStore = create<AppState & AppActions>()(
// Feature Default Settings actions
setDefaultSkipTests: (skip) => set({ defaultSkipTests: skip }),
setEnableDependencyBlocking: (enabled) => set({ enableDependencyBlocking: enabled }),
setEnableDependencyBlocking: (enabled) =>
set({ enableDependencyBlocking: enabled }),
// Worktree Settings actions
setUseWorktrees: (enabled) => set({ useWorktrees: enabled }),
@@ -1380,6 +1391,18 @@ export const useAppStore = create<AppState & AppActions>()(
return get().worktreesByProject[projectPath] ?? [];
},
isPrimaryWorktreeBranch: (projectPath, branchName) => {
const worktrees = get().worktreesByProject[projectPath] ?? [];
const primary = worktrees.find((w) => w.isMain);
return primary?.branch === branchName;
},
getPrimaryWorktreeBranch: (projectPath) => {
const worktrees = get().worktreesByProject[projectPath] ?? [];
const primary = worktrees.find((w) => w.isMain);
return primary?.branch ?? null;
},
// Profile Display Settings actions
setShowProfilesOnly: (enabled) => set({ showProfilesOnly: enabled }),
@@ -2237,7 +2260,8 @@ export const useAppStore = create<AppState & AppActions>()(
// Settings
apiKeys: state.apiKeys,
maxConcurrency: state.maxConcurrency,
autoModeByProject: state.autoModeByProject,
// Note: autoModeByProject is intentionally NOT persisted
// Auto-mode should always default to OFF on app refresh
defaultSkipTests: state.defaultSkipTests,
enableDependencyBlocking: state.enableDependencyBlocking,
useWorktrees: state.useWorktrees,