Skip to content

desktop: native macOS toolbar, consistent page design, and snappier navigation#9263

Draft
h3nock wants to merge 31 commits into
BasedHardware:mainfrom
h3nock:desktop-native-toolbar-consistent-ui
Draft

desktop: native macOS toolbar, consistent page design, and snappier navigation#9263
h3nock wants to merge 31 commits into
BasedHardware:mainfrom
h3nock:desktop-native-toolbar-consistent-ui

Conversation

@h3nock

@h3nock h3nock commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What

Reworks the desktop app chrome and page design language toward native macOS, and cuts navigation waste. Three themes:

1. Native macOS unified toolbar. Replaces the in-content header chrome with a real NSToolbar (.windowToolbarStyle(.unified)): traffic lights, a Home affordance + page title on the left, and Capture / Listening / Settings on the right — all in the system title bar. Capture and Listening are labeled with a readable on/off state (green-tinted when running, amber when blocked, dimmed when off), not a tiny badge. Toolbar glyphs stay neutral (no purple). The window content now runs edge-to-edge under the toolbar instead of sitting in a nested rounded card.

2. Consistent page design language. A shared header-control kit (OmiHeaderControls) unifies the search field, filter chips, and icon buttons across Conversations, Tasks, Memories, and Rewind — one capsule search, one chip style, one circular icon button, one active-state treatment. Replaces the previous mix of radius-8 squares, 42pt white squares, and assorted chip heights. Task rows are cleaned up (detail button moved into the hover cluster instead of a permanent badge line, checkbox aligned to the first text line). The chat input collapses from a field-inside-a-panel into a single surface.

3. Snappier navigation. Pages were recreated on every tab switch, so page-held state and TTLs died per visit (Home refetched all status data every visit; the brain map re-ran an 800-tick force layout and rebuilt the SceneKit scene every Memories visit). Hoisted into session-persistent owners in ViewModelContainer:

  • HomeStatusStore — counts/connector/MCP statuses behind a 60s activation throttle + single-flight
  • ConversationsSearchModel — query + debounce + results survive navigation
  • shared MemoryGraphViewModel — scene persists; skips re-simulation when the graph content-signature is unchanged; on-disk layout cache (FNV-1a keyed) restores a settled layout in ~1ms vs a multi-thousand-ms cold sim

Verification

  • xcrun swift build -c debug --package-path Desktop
  • xcrun swift test -c debug --package-path Desktop --filter DashboardCaptureStateTests
  • xcrun swift test -c debug --package-path Desktop --filter ImportConnectorStatusStoreTests
  • xcrun swift test -c debug --package-path Desktop --filter ScreenRecordingPermissionPolicyTests
  • python3 scripts/check-e2e-flow-coverage.py --strict --base upstream/main
  • python3 scripts/check-userdefaults-key-ratchet.py --print
  • git diff --check
  • Rebased onto current upstream/main; conflict resolved by keeping the shared toolbar controller and porting upstream's screen-recording permission helper into it.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 23 files

Confidence score: 3/5

  • desktop/macos/Desktop/Sources/Stores/HomeStatusStore.swift has a race where resetSessionState() can run while an in-flight refresh() resumes and writes stale per-account data, so account switches/sign-out can show the wrong status for the new session — add cancellation/epoch guards so refresh() results are ignored after reset before merging.
  • desktop/macos/Desktop/Sources/Stores/HomeStatusStore.swift also leaves importConnectorStatusStore intact on reset, which can leak connector badge state across users and show incorrect connected indicators after sign-out/switch — clear or reinitialize that nested store in resetSessionState() to keep session boundaries clean.
  • desktop/macos/Desktop/Sources/MainWindow/Pages/MemoryGraph/MemoryGraphPage.swift consumes hasRunEmptyBootstrap before rebuildGraph() succeeds, so one transient failure can disable empty-graph bootstrap for the rest of the session and leave the page stuck without expected recovery — only flip the latch after a successful rebuild (or retry/fallback on failure).
  • desktop/macos/Desktop/Sources/MainWindow/DesktopHomeView.swift applies unified toolbar styling even when useLegacyHomeDesign hides mainToolbar, which can yield an empty toolbar in legacy mode and a visibly broken header — gate the unified style with the same flag or provide a legacy toolbar fallback before merging.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/Stores/HomeStatusStore.swift
Comment thread desktop/macos/Desktop/Sources/Stores/HomeStatusStore.swift
Comment thread desktop/macos/Desktop/Sources/MainWindow/DesktopHomeView.swift Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 17 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/Stores/HomeStatusStore.swift
Comment thread desktop/macos/Desktop/Sources/Onboarding/OnboardingPagedIntroCoordinator.swift Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread desktop/macos/Desktop/Sources/Stores/HomeStatusStore.swift
Comment thread desktop/macos/Desktop/Tests/DashboardCaptureStateTests.swift Outdated
h3nock added 27 commits July 8, 2026 00:58
@h3nock h3nock force-pushed the desktop-native-toolbar-consistent-ui branch from bd68e39 to 61f7e14 Compare July 8, 2026 05:06
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

We like most of the work in this PR: the faster page navigation, persistent Home/search state, memory graph improvements, page consistency, and cleanup all look directionally good. The native macOS toolbar/nav treatment does not feel on-brand for Omi, though, so we plan to revert that piece while preserving the rest of the improvements.

Preserve the PR's navigation/state improvements while moving the Home/status affordances out of the native macOS toolbar and back into the app surface.

Verification:

- cd desktop/macos && xcrun swift build -c debug --package-path Desktop

- cd desktop/macos && xcrun swift test --package-path Desktop --filter DashboardCaptureStateTests

- cd desktop/macos && TMPDIR=/tmp/omi-pr-9263-inappnav-run OMI_APP_NAME="omi-pr-9263-inappnav" ./run.sh --yolo

- cd desktop/macos && OMI_AUTOMATION_PORT=47919 ./scripts/omi-ctl state
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Pushed a follow-up commit to keep the PR’s non-toolbar improvements while moving the nav/status chrome back into the app surface.

Remaining feedback:

  • The nav/header still is not fully restored or polished enough yet. The native macOS toolbar direction was not on-brand, and the in-app restoration still needs UI/UX tuning before merge: spacing, title/back affordance, status-control placement, and page-to-page consistency all need another pass.
  • The footgun level is better, but still not low enough. The PR moves more state to longer-lived owners, which is directionally good, but the new stores/controllers still lean on singletons, UserDefaults, NotificationCenter, and silent try? fallbacks. That leaves too many paths where failures can become stale UI instead of explicit, testable states.
  • Testing is still thin for the amount of behavior being moved. The current coverage is mostly source-inspection tests plus a few UserDefaults/session-scope tests. We should add more behavioral coverage around search cancellation/order, Home refresh failure/freshness states, memory graph runtime behavior, and manual or automation-backed visual QA for the page chrome.

So overall: we like most of the work and should preserve the performance/state improvements, but this is not yet at a low-footgun, easy-to-maintain bar until the remaining chrome polish and behavioral tests are tightened.

@h3nock h3nock marked this pull request as draft July 9, 2026 00:50
@Git-on-my-level Git-on-my-level added needs-maintainer-review Needs human maintainer review before merge needs-tests PR introduces logic that should be covered by tests security-review Touches auth, provider routing, secrets, or security-sensitive surfaces labels Jul 9, 2026

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the follow-up here — the non-toolbar performance/state work is directionally useful, but I found one blocker before this is merge-ready:

  • ViewModelContainer.resetStartupState() resets the Home/search/task/memory/app stores on account changes, but it does not reset or replace the session-persistent memoryGraphViewModel. Since this PR intentionally makes the brain-map scene/layout long-lived, signing out or switching accounts can leave the previous user's memory graph nodes/edges and SceneKit scene visible to the next account until a later refresh replaces it. That is a cross-account stale-data/privacy leak, not just a freshness issue. Please add an explicit reset path for MemoryGraphViewModel (clear scene nodes/edges, simulation, loaded signature/cache state, loading/bootstrap flags, selected node, etc.) and cover it with a behavioral account-switch/session reset test.

Keeping this as request-changes because it affects user memory data isolation. I agree with the existing maintainer direction that the remaining chrome polish and behavioral coverage should also be tightened before merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-maintainer-review Needs human maintainer review before merge needs-tests PR introduces logic that should be covered by tests security-review Touches auth, provider routing, secrets, or security-sensitive surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants