Fix workspace notification ring invalidation blanking active terminal

Closed
AU
1mo ago
+479-83

Summary

  • add a workspace-scoped notification presentation model and regression tests
  • update workspace content to observe notification changes only for its own workspace
  • update sidebar rows to observe their own workspace notification presentation so background workspaces do not invalidate sibling rows

Closes #2887


[!NOTE]
Medium Risk
Touches notification indexing and several UI update paths (workspace content, sidebar rows, command palette) via new snapshot/publisher logic; regressions could cause stale/missing badges or rings but the scope is localized and covered by new tests.

Overview
Fixes cross-workspace notification updates from invalidating unrelated UI by introducing a per-workspace notification snapshot model and publishers.

TerminalNotificationStore now builds and publishes TerminalNotificationWorkspaceSnapshot (unread/read presence, per-surface visibility including focused read indicator, latest notification), plus per-tab WorkspaceNotificationPresentationStore instances cached via WorkspaceNotificationPresentationStoreCache.

ContentView, WorkspaceContentView, and sidebar TabItemView are refactored to consume these workspace-scoped snapshots/stores (including tmux overlay/unread rect calculations and command palette context flags), with cache pruning on tab changes. Adds regression tests for snapshot correctness, per-workspace isolation, stale-snapshot fallback, and cache pruning, plus a small File Explorer test stabilization around pending expansion completion.

Reviewed by Cursor Bugbot for commit fc4843147d182ee4873172019dbf47d1fde1e81b. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fixes a bug where notifications from other workspaces invalidated the active workspace and blanked its terminal. Scopes notification state per workspace so rings/overlays, sidebar badges, and the command palette stay accurate and reactive. Closes #2887.

  • Bug Fixes
    • Added a per-workspace TerminalNotificationWorkspaceSnapshot (unread count, read presence, per-surface unread and visible sets incl. focused read indicator, latest notification).
    • Introduced per-tab WorkspaceNotificationPresentationStore cached via WorkspaceNotificationPresentationStoreCache; sidebar rows observe their own store for unread count and latest message to avoid cross-row invalidation and flicker.
    • ContentView caches the selected workspace snapshot, updates it via workspaceSnapshotPublisher(forTabId:), prunes stale presentation stores on tab changes, uses visibleSurfaceIds for unread rects, and drives command palette read/unread from snapshots.
    • WorkspaceContentView subscribes to workspaceSnapshotPublisher(forTabId:) and uses visibleSurfaceIds for unread rings and tmux overlay rects.
    • Switched views to TerminalNotificationStore.shared to reduce environment-driven invalidations; added publishers (presentationPublisher/workspaceSnapshotPublisher) for reactive updates.
    • Tests cover presentation isolation, latest+focused indicator inclusion, stale-snapshot fallback, and cache pruning; stabilized File Explorer hydration by awaiting pending expansions.

Summary by CodeRabbit

  • Refactor

    • Notification state moved to per-workspace snapshots with cached per-tab presentation stores to reduce per-row observation and improve responsiveness when switching tabs/workspaces.
  • New Features

    • Sidebar and tab badges now derive unread/visible indicators from workspace snapshots for more accurate, consistent updates.
  • Bug Fixes

    • Reduced unnecessary badge recomputation and UI churn; notification overlays more stable. Also ensured certain async file-explorer tasks run on the main actor to avoid timing issues.
  • Tests

    • Added tests covering presentation/snapshot behavior and notification visibility across workspaces.