diff --git a/src/renderer/src/hooks/useUnreadDockBadge.ts b/src/renderer/src/hooks/useUnreadDockBadge.ts index 1f6674a9824..5fa6b8876f8 100644 --- a/src/renderer/src/hooks/useUnreadDockBadge.ts +++ b/src/renderer/src/hooks/useUnreadDockBadge.ts @@ -6,6 +6,7 @@ export function useUnreadDockBadge(): void { const unreadCount = useAppStore((state) => getUnreadBadgeCount({ worktreesByRepo: state.worktreesByRepo, + detectedWorktreesByRepo: state.detectedWorktreesByRepo, tabsByWorktree: state.tabsByWorktree, unreadTerminalTabs: state.unreadTerminalTabs }) diff --git a/src/renderer/src/lib/unread-badge-count.test.ts b/src/renderer/src/lib/unread-badge-count.test.ts index fdf20dfab30..60cf5b3173b 100644 --- a/src/renderer/src/lib/unread-badge-count.test.ts +++ b/src/renderer/src/lib/unread-badge-count.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import type { TerminalTab, Worktree } from '../../../shared/types' +import type { DetectedWorktreeListResult, TerminalTab, Worktree } from '../../../shared/types' import { getUnreadBadgeCount } from './unread-badge-count' function worktree(id: string, isUnread: boolean): Worktree { @@ -10,6 +10,23 @@ function tab(id: string): TerminalTab { return { id } as TerminalTab } +function detectedWorktree(id: string, isUnread: boolean): DetectedWorktreeListResult { + return { + repoId: 'repo', + authoritative: true, + source: 'git', + worktrees: [ + { + ...worktree(id, isUnread), + repoId: 'repo', + ownership: 'orca-managed', + selectedCheckout: false, + visible: true + } + ] + } as DetectedWorktreeListResult +} + describe('getUnreadBadgeCount', () => { it('counts unread worktrees', () => { expect( @@ -40,4 +57,15 @@ describe('getUnreadBadgeCount', () => { }) ).toBe(2) }) + + it('counts automatic unread markers on detected worktrees', () => { + expect( + getUnreadBadgeCount({ + worktreesByRepo: { repo: [] }, + detectedWorktreesByRepo: { repo: detectedWorktree('wt-detected', true) }, + tabsByWorktree: {}, + unreadTerminalTabs: {} + }) + ).toBe(1) + }) }) diff --git a/src/renderer/src/lib/unread-badge-count.ts b/src/renderer/src/lib/unread-badge-count.ts index 79cd2ffa36b..7841618cfa2 100644 --- a/src/renderer/src/lib/unread-badge-count.ts +++ b/src/renderer/src/lib/unread-badge-count.ts @@ -1,11 +1,13 @@ -import type { TerminalTab, Worktree } from '../../../shared/types' +import type { DetectedWorktreeListResult, TerminalTab, Worktree } from '../../../shared/types' export function getUnreadBadgeCount({ worktreesByRepo, + detectedWorktreesByRepo = {}, tabsByWorktree, unreadTerminalTabs }: { worktreesByRepo: Record + detectedWorktreesByRepo?: Record tabsByWorktree: Record unreadTerminalTabs: Record }): number { @@ -19,6 +21,16 @@ export function getUnreadBadgeCount({ } } + // Why: automatic agent attention can land while a worktree is only present + // in detectedWorktreesByRepo; the Dock badge must mirror that unread marker. + for (const result of Object.values(detectedWorktreesByRepo)) { + for (const worktree of result.worktrees) { + if (worktree.isUnread) { + unreadWorktreeIds.add(worktree.id) + } + } + } + const unreadTabIds = new Set(Object.keys(unreadTerminalTabs)) if (unreadTabIds.size === 0) { return unreadWorktreeIds.size