From 09527b3b67fd3b9221532767f7e022e1a8ac06ce Mon Sep 17 00:00:00 2001 From: Kacper Date: Sat, 10 Jan 2026 23:43:52 +0100 Subject: [PATCH] feat: Add auto-dismiss functionality for Init Script Indicator This commit introduces an auto-dismiss feature for the Init Script Indicator, enhancing user experience by automatically hiding the indicator 5 seconds after the script completes. Key changes include: 1. **State Management**: Added `autoDismissInitScriptIndicatorByProject` to manage the auto-dismiss setting per project. 2. **UI Components**: Updated the WorktreesSection to include a toggle for enabling or disabling the auto-dismiss feature, allowing users to customize their experience. 3. **Indicator Logic**: Implemented logic in the SingleIndicator component to handle auto-dismiss based on the new setting. These enhancements provide users with more control over the visibility of the Init Script Indicator, streamlining project management workflows. --- .../board-view/init-script-indicator.tsx | 24 ++++++++++++- .../worktrees/worktrees-section.tsx | 34 +++++++++++++++++++ apps/ui/src/store/app-store.ts | 24 +++++++++++++ libs/types/src/settings.ts | 2 ++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/apps/ui/src/components/views/board-view/init-script-indicator.tsx b/apps/ui/src/components/views/board-view/init-script-indicator.tsx index a039f58b..33298394 100644 --- a/apps/ui/src/components/views/board-view/init-script-indicator.tsx +++ b/apps/ui/src/components/views/board-view/init-script-indicator.tsx @@ -13,9 +13,16 @@ interface SingleIndicatorProps { state: InitScriptState; onDismiss: (key: string) => void; isOnlyOne: boolean; // Whether this is the only indicator shown + autoDismiss: boolean; // Whether to auto-dismiss after completion } -function SingleIndicator({ stateKey, state, onDismiss, isOnlyOne }: SingleIndicatorProps) { +function SingleIndicator({ + stateKey, + state, + onDismiss, + isOnlyOne, + autoDismiss, +}: SingleIndicatorProps) { const [showLogs, setShowLogs] = useState(false); const logsEndRef = useRef(null); @@ -35,6 +42,16 @@ function SingleIndicator({ stateKey, state, onDismiss, isOnlyOne }: SingleIndica } }, [status, isOnlyOne]); + // Auto-dismiss after completion (5 seconds) + useEffect(() => { + if (autoDismiss && (status === 'success' || status === 'failed')) { + const timer = setTimeout(() => { + onDismiss(stateKey); + }, 5000); + return () => clearTimeout(timer); + } + }, [status, autoDismiss, stateKey, onDismiss]); + if (status === 'idle') return null; return ( @@ -123,8 +140,12 @@ function SingleIndicator({ stateKey, state, onDismiss, isOnlyOne }: SingleIndica export function InitScriptIndicator({ projectPath }: InitScriptIndicatorProps) { const getInitScriptStatesForProject = useAppStore((s) => s.getInitScriptStatesForProject); const clearInitScriptState = useAppStore((s) => s.clearInitScriptState); + const getAutoDismissInitScriptIndicator = useAppStore((s) => s.getAutoDismissInitScriptIndicator); const [dismissedKeys, setDismissedKeys] = useState>(new Set()); + // Get auto-dismiss setting + const autoDismiss = getAutoDismissInitScriptIndicator(projectPath); + // Get all init script states for this project const allStates = getInitScriptStatesForProject(projectPath); @@ -180,6 +201,7 @@ export function InitScriptIndicator({ projectPath }: InitScriptIndicatorProps) { state={state} onDismiss={handleDismiss} isOnlyOne={activeStates.length === 1} + autoDismiss={autoDismiss} /> ))} diff --git a/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx b/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx index 4a281995..fd43f3d0 100644 --- a/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx +++ b/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx @@ -37,6 +37,8 @@ export function WorktreesSection({ useWorktrees, onUseWorktreesChange }: Worktre const setShowInitScriptIndicator = useAppStore((s) => s.setShowInitScriptIndicator); const getDefaultDeleteBranch = useAppStore((s) => s.getDefaultDeleteBranch); const setDefaultDeleteBranch = useAppStore((s) => s.setDefaultDeleteBranch); + const getAutoDismissInitScriptIndicator = useAppStore((s) => s.getAutoDismissInitScriptIndicator); + const setAutoDismissInitScriptIndicator = useAppStore((s) => s.setAutoDismissInitScriptIndicator); const [scriptContent, setScriptContent] = useState(''); const [originalContent, setOriginalContent] = useState(''); const [scriptExists, setScriptExists] = useState(false); @@ -54,6 +56,11 @@ export function WorktreesSection({ useWorktrees, onUseWorktreesChange }: Worktre ? getDefaultDeleteBranch(currentProject.path) : false; + // Get the auto-dismiss setting + const autoDismiss = currentProject?.path + ? getAutoDismissInitScriptIndicator(currentProject.path) + : true; + // Check if there are unsaved changes const hasChanges = scriptContent !== originalContent; @@ -233,6 +240,33 @@ export function WorktreesSection({ useWorktrees, onUseWorktreesChange }: Worktre )} + {/* Auto-dismiss Init Script Indicator Toggle */} + {currentProject && showIndicator && ( +
+ { + if (currentProject?.path) { + setAutoDismissInitScriptIndicator(currentProject.path, checked === true); + } + }} + className="mt-1" + /> +
+ +

+ Automatically hide the indicator 5 seconds after the script completes. +

+
+
+ )} + {/* Default Delete Branch Toggle */} {currentProject && (
diff --git a/apps/ui/src/store/app-store.ts b/apps/ui/src/store/app-store.ts index 2d9f42da..7b19a1ab 100644 --- a/apps/ui/src/store/app-store.ts +++ b/apps/ui/src/store/app-store.ts @@ -673,6 +673,10 @@ export interface AppState { // Whether to default the "delete branch" checkbox when deleting a worktree (default: false) defaultDeleteBranchByProject: Record; + // Auto-dismiss Init Script Indicator (per-project, keyed by project path) + // Whether to auto-dismiss the indicator after completion (default: true) + autoDismissInitScriptIndicatorByProject: Record; + // UI State (previously in localStorage, now synced via API) /** Whether worktree panel is collapsed in board view */ worktreePanelCollapsed: boolean; @@ -1094,6 +1098,10 @@ export interface AppActions { setDefaultDeleteBranch: (projectPath: string, deleteBranch: boolean) => void; getDefaultDeleteBranch: (projectPath: string) => boolean; + // Auto-dismiss Init Script Indicator actions (per-project) + setAutoDismissInitScriptIndicator: (projectPath: string, autoDismiss: boolean) => void; + getAutoDismissInitScriptIndicator: (projectPath: string) => boolean; + // UI State actions (previously in localStorage, now synced via API) setWorktreePanelCollapsed: (collapsed: boolean) => void; setLastProjectDir: (dir: string) => void; @@ -1233,6 +1241,7 @@ const initialState: AppState = { worktreePanelVisibleByProject: {}, showInitScriptIndicatorByProject: {}, defaultDeleteBranchByProject: {}, + autoDismissInitScriptIndicatorByProject: {}, // UI State (previously in localStorage, now synced via API) worktreePanelCollapsed: false, lastProjectDir: '', @@ -3179,6 +3188,21 @@ export const useAppStore = create()((set, get) => ({ return get().defaultDeleteBranchByProject[projectPath] ?? false; }, + // Auto-dismiss Init Script Indicator actions (per-project) + setAutoDismissInitScriptIndicator: (projectPath, autoDismiss) => { + set({ + autoDismissInitScriptIndicatorByProject: { + ...get().autoDismissInitScriptIndicatorByProject, + [projectPath]: autoDismiss, + }, + }); + }, + + getAutoDismissInitScriptIndicator: (projectPath) => { + // Default to true (auto-dismiss enabled) if not set + return get().autoDismissInitScriptIndicatorByProject[projectPath] ?? true; + }, + // UI State actions (previously in localStorage, now synced via API) setWorktreePanelCollapsed: (collapsed) => set({ worktreePanelCollapsed: collapsed }), setLastProjectDir: (dir) => set({ lastProjectDir: dir }), diff --git a/libs/types/src/settings.ts b/libs/types/src/settings.ts index 1b8f37d4..ab16d03d 100644 --- a/libs/types/src/settings.ts +++ b/libs/types/src/settings.ts @@ -601,6 +601,8 @@ export interface ProjectSettings { // Worktree Behavior /** Default value for "delete branch" checkbox when deleting a worktree (default: false) */ defaultDeleteBranchWithWorktree?: boolean; + /** Auto-dismiss init script indicator after completion (default: true) */ + autoDismissInitScriptIndicator?: boolean; // Session Tracking /** Last chat session selected in this project */