|
1 | 1 | import { useState, useEffect, useCallback, useRef, useMemo } from 'react' |
2 | | -import type { Worktree, TerminalTab, PtyStatus, PRStatus, QuestStep, WorkspacePane, PendingWorktree, UpdaterStatus } from './types' |
| 2 | +import type { Worktree, TerminalTab, PtyStatus, PendingTool, PRStatus, QuestStep, WorkspacePane, PendingWorktree, UpdaterStatus } from './types' |
3 | 3 | import type { Action } from './hotkeys' |
4 | 4 | import { resolveHotkeys } from './hotkeys' |
5 | 5 | import { HotkeysProvider } from './components/Tooltip' |
@@ -73,6 +73,7 @@ export default function App(): JSX.Element { |
73 | 73 | return out |
74 | 74 | }, [panes, activePaneId]) |
75 | 75 | const [statuses, setStatuses] = useState<Record<string, PtyStatus>>({}) |
| 76 | + const [pendingTools, setPendingTools] = useState<Record<string, PendingTool | null>>({}) |
76 | 77 | const [prStatuses, setPrStatuses] = useState<Record<string, PRStatus | null>>({}) |
77 | 78 | const [mergedPaths, setMergedPaths] = useState<Record<string, boolean>>({}) |
78 | 79 | const [prLoading, setPrLoading] = useState(false) |
@@ -534,9 +535,14 @@ const setQuestStep = useCallback((next: QuestStep) => { |
534 | 535 |
|
535 | 536 | // Listen for status changes from main process |
536 | 537 | useEffect(() => { |
537 | | - const cleanup = window.api.onStatusChange((id, status) => { |
| 538 | + const cleanup = window.api.onStatusChange((id, status, pendingTool) => { |
538 | 539 | console.log(`[status] received: id=${id} status=${status}`) |
539 | 540 | setStatuses((prev) => ({ ...prev, [id]: status as PtyStatus })) |
| 541 | + setPendingTools((prev) => { |
| 542 | + const next = status === 'needs-approval' ? pendingTool : null |
| 543 | + if (prev[id] === next) return prev |
| 544 | + return { ...prev, [id]: next } |
| 545 | + }) |
540 | 546 | const wtPath = terminalToWorktree(id) |
541 | 547 | if (wtPath) { |
542 | 548 | markActive(wtPath) |
@@ -1428,19 +1434,23 @@ const setQuestStep = useCallback((next: QuestStep) => { |
1428 | 1434 |
|
1429 | 1435 | // Compute aggregate status per worktree (worst status wins) |
1430 | 1436 | const worktreeStatuses: Record<string, PtyStatus> = {} |
| 1437 | + const worktreePendingTools: Record<string, PendingTool | null> = {} |
1431 | 1438 | for (const wt of worktrees) { |
1432 | 1439 | const tabs = terminalTabs[wt.path] || [] |
1433 | 1440 | let worstStatus: PtyStatus = 'idle' |
| 1441 | + let pending: PendingTool | null = null |
1434 | 1442 | for (const tab of tabs) { |
1435 | 1443 | const s = statuses[tab.id] |
1436 | 1444 | if (s === 'needs-approval') { |
1437 | 1445 | worstStatus = 'needs-approval' |
| 1446 | + pending = pendingTools[tab.id] || null |
1438 | 1447 | break |
1439 | 1448 | } |
1440 | 1449 | if (s === 'waiting' && worstStatus !== 'needs-approval') worstStatus = 'waiting' |
1441 | 1450 | if (s === 'processing' && worstStatus === 'idle') worstStatus = 'processing' |
1442 | 1451 | } |
1443 | 1452 | worktreeStatuses[wt.path] = worstStatus |
| 1453 | + worktreePendingTools[wt.path] = pending |
1444 | 1454 | } |
1445 | 1455 |
|
1446 | 1456 | // Record activity-log transitions whenever a worktree's effective state changes. |
@@ -1596,6 +1606,7 @@ const setQuestStep = useCallback((next: QuestStep) => { |
1596 | 1606 | pendingWorktrees={pendingWorktrees} |
1597 | 1607 | activeWorktreeId={activeWorktreeId} |
1598 | 1608 | statuses={worktreeStatuses} |
| 1609 | + pendingTools={worktreePendingTools} |
1599 | 1610 | prStatuses={prStatuses} |
1600 | 1611 | mergedPaths={mergedPaths} |
1601 | 1612 | prLoading={prLoading} |
@@ -1704,6 +1715,7 @@ const setQuestStep = useCallback((next: QuestStep) => { |
1704 | 1715 | <CommandCenter |
1705 | 1716 | worktrees={worktrees} |
1706 | 1717 | worktreeStatuses={worktreeStatuses} |
| 1718 | + worktreePendingTools={worktreePendingTools} |
1707 | 1719 | prStatuses={prStatuses} |
1708 | 1720 | mergedPaths={mergedPaths} |
1709 | 1721 | lastActive={lastActive} |
|
0 commit comments