Fix dock unread badge for detected worktrees

Automatic agent completion and permission attention can mark a worktree unread before it is present in worktreesByRepo. Include detectedWorktreesByRepo in the unread badge count so the macOS Dock badge follows the same unread state as the in-app markers.
This commit is contained in:
Neil
2026-05-29 07:41:06 -07:00
parent 6c553ef4b3
commit 03e51e0ec2
3 changed files with 43 additions and 2 deletions
@@ -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
})
@@ -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)
})
})
+13 -1
View File
@@ -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<string, Worktree[]>
detectedWorktreesByRepo?: Record<string, DetectedWorktreeListResult>
tabsByWorktree: Record<string, TerminalTab[]>
unreadTerminalTabs: Record<string, true>
}): 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