* feat(macos): native-feel dashboard hosting: instant reopen, preload, frame autosave, ⌘N/⌘K, route memory
The hosted Control UI dashboard now skips SPA reloads when reopening an
unchanged endpoint (auth-equality gated), preloads after launch when a
credentialed local/direct config exists, autosaves its window frame, maps
⌘N/⌘K menu items onto the shipped native web events, filters browser-tell
context-menu items, restores the last committed route via web-side
localStorage memory, and themes the pre-paint background.
* refactor(ui): satisfy TS LOC ratchet: move optional lazy-element helpers out of app-host
app-host.ts is over the 500-line ratchet ceiling and may not grow; move the
self-contained optional custom-element block into lazy-custom-element.ts (its
natural owner) and fold the route-restore decision into native-route-memory's
considerRouteRestore so the shell only replaces-or-persists.
* fix(macos): recover stuck dashboard command queue via deliverability gate
Replace the failure-page-only fast-path check with canDeliverNativeCommands
(live document or in-flight load); a terminally cancelled reload now falls
through to the reload path instead of queueing ⌘N/⌘K forever.
* fix(ui): let in-flight navigation win over native route restore
The one-shot startup restore now checks the rendered/pending match against
the committed bootstrap route; an explicit navigation already in flight
(replayed native new-session, fast click) is no longer clobbered.
* docs(ui): note idempotent collapse of pending native new-session replays
* fix(macos): drop queued dashboard commands on terminal load failure
Queued ⌘N/⌘K are moment-bound; surviving a failure page meant a later
recovery reload replayed stale commands (double palette toggle nets closed,
surprise navigation). Both failure entry points now clear the queue.
* fix(ui): persist native route memory only for settled router states
Mid-navigation emissions still carry the stale committed bootstrap route; an
interrupted restore could overwrite the remembered destination with it.
* fix(macos): coalesce dashboard opens for queued native commands
One in-flight open drains a manager-level queue in press order; a Task per
key press could race window creation (duplicate windows) and reorder ⌘N/⌘K
delivery on the non-immediate remote path.
* fix(macos): correct dashboard placement after frame-autosave restore
setFrameAutosaveName re-applies the stored frame; run ensureOnScreen after
both autosave-name assignments so a frame saved on a disconnected monitor
cannot restore the window off-screen.
* fix(macos): clear dashboard failure state when history restores a real document
Swipe-back/⌘[ off the failure page commits an http(s) document without
passing through load(); the flag previously stayed set and forced a reload
on the next native command.
* fix(macos): keep in-flight dashboard loads instead of restarting them
An open/update during the launch preload previously cancelled and restarted
the same-URL load; in-flight non-failure documents now count as usable in
the reload decision.
* fix(macos,ui): ⌘K legacy fallback + transient search param filtering
Command palette dispatch now sends a cancelable toggle event and falls back
to the shipped open-search event when no handler acknowledges it, so ⌘K
keeps working against older gateway-served bundles. Route memory strips
one-shot action params (?draft=) before persisting; navigation state like
?session= still restores.
* chore(i18n): register dashboard menu strings + drop unused route-memory export
native:i18n:sync inventory + per-locale artifacts for New Session / Command
Palette…; StoredNativeRoute is module-internal after the considerRouteRestore
refactor (deadcode exports gate).
* chore(i18n): rebaseline raw-copy for relocated lazy-element labels
The lazy-custom-element extraction moved three internal load-failure labels
out of app-host.ts; refresh the keyless raw-copy baseline to match (main's
new ui:i18n:verify gate).
* fix(macos): center dashboard traffic lights with the hosted titlebar buttons
Give the dashboard window an empty unified toolbar so its titlebar grows
to 52pt, vertically centering the macOS traffic lights against the row of
web-hosted titlebar buttons (sidebar toggle, back/forward) instead of
hugging the top edge. Bump the injected --openclaw-native-titlebar-height
to match, and nudge the hosted controls' left offset from 78px to 92px so
the traffic-light cluster and the first web button read as separate groups.
The toolbar exists only to size the titlebar, so View > Hide Toolbar (and
the corresponding shortcut) are refused; hiding it would collapse the
titlebar while the web inset stays pinned at 52pt, resurrecting the
misalignment. Smoke tests cover toolbar presence/style, hide refusal, and
the exact injected height.
* chore(i18n): resync native inventory line metadata
* feat(mac): swap dashboard titlebar buttons with sidebar state
The Control UI reports sidebar collapsed/width over a new openclawNav
WKScriptMessage; the titlebar accessory shows toggle+back/forward
right-aligned to the sidebar edge while expanded, and
toggle+search+new-session while collapsed. Search opens the command
palette and + opens the new-session surface via openclaw:native-*
events. Older gateway bundles that never report keep the shipped
toggle/back/forward layout.
Refs #105129
* docs: describe state-dependent mac titlebar buttons
* fix(macos): host the dashboard sidebar toggle beside back/forward in the titlebar
The Control UI's floating sidebar-expand button rendered as a bordered web
control crowding the traffic lights in the dashboard window. The toggle now
lives as a native borderless button in the leading titlebar accessory ahead
of back/forward (Safari ordering) and bridges to the web UI via the
openclaw:native-toggle-sidebar event; the injected chrome script advertises
the capability with an openclaw-native-nav class so the web control retires
itself visually while staying keyboard/screen-reader reachable.
* docs: note the macOS app's native titlebar sidebar toggle in the Control UI guide
* fix(mac): prerelease-exact launch resolution and policy-aware update ownership
* fix(ui): keep update affordance when nav is hidden and fall back on native decline
* chore(i18n): sync native inventory
* feat: sidebar update card (web + macOS) with app-first mac update flow and Sparkle beta track
Squashed from claude/update-notification-display-c6cfb9 after semantic merge
with #104178 (channel-aware CLI installs). See PR #104171 body for details.
* chore(i18n): resync generated inventories after rebase
* chore(i18n): resync locale metadata after rebase
* fix(macos): drag the window from split-view pane headers
In the macOS app, split-screen pane header rows (session title strip) now
start a native window drag instead of selecting the title text. The Control
UI posts an openclawWindowDrag script message on mousedown over passive
header chrome; the dashboard window validates the trusted main-frame source
and the in-flight left-mouse press before calling NSWindow.performDrag.
Pane headers are chrome, so they are also no longer text-selectable.
* refactor(macos): move the dashboard failure page out of the window controller
SwiftLint type_body_length: the drag-message handler pushed
DashboardWindowController past 800 lines; the failure-page HTML is
presentation-only and now lives in DashboardFailurePage.
* feat(ui): restore sidebar chrome and remove the pane workspace strip
Reverse course from #103426 on the app chrome: the left sidebar owns
brand, pinned navigation + More, New session, sessions, and the footer
(status dot, Settings, Docs, pairing, theme) again, and the desktop
topbar is gone. What stays from that PR: the dockable workspace rail
(right/bottom, drag or button), the in-flow split-pane headers, and
Cmd+B now hides the sidebar entirely (no 78px icon rail) with a
floating expand control.
The real target of the original request: the vertical icon strip at
each pane's right edge is deleted. A collapsed workspace rail renders
nothing; the toggle (with a changed-file badge) lives in the split-pane
header next to split/close, or floats at the top-right in single-pane
chat. Shift+Cmd+B still toggles.
Narrow native macOS windows (e.g. the in-app link browser splitting
the window) previously stacked 50px of injected titlebar padding on
top of the 58px drawer row; the web CSS now folds that into one
compact 58px row beside the traffic lights, with selectors that
outrank the rules shipped Mac apps inject.
* chore(ui): regenerate locale bundles and docs map for sidebar restore
* fix(ui): bind showPaneHeader explicitly on the classic single pane
* chore(ui): reconcile locale metadata after rebase onto lobster wild cards
* feat(ui): move app chrome into a topbar and dock the session workspace rail
The desktop shell now uses a slim topbar for brand, primary navigation
(Chat + pinned routes + More menu), command-palette search, pairing,
theme, and Settings; the left column slims down to a sessions-only
panel (Cmd+B hides it entirely — the 78px icon rail is gone). Split
view drops the fixed geometry-mirroring toolbar for in-flow per-pane
headers. The session workspace rail can dock right or bottom inside
its pane — drag its header between edges or use the dock button — and
the collapsed strip's file glyph is now a real button (it used to be a
dead, button-looking span) with a changed-file count badge. The Mac
app's injected chrome CSS slims down accordingly; its drag-region
geometry is unchanged and the topbar brand strip stays passive under
it.
* chore(ui): regenerate locale bundles for topbar and workspace dock strings
* fix(ui): keep the native macOS drawer clear of the titlebar overlay
The narrow-width slide-over drawer sits fixed at the window top, over
the AppKit traffic lights and drag regions. The old Mac-app-injected
CSS padded .sidebar-shell for this; that rule moved web-side for the
desktop topbar, so restore drawer clearance here for both the app
drawer and the in-drawer settings sidebar.
* chore(ui): translate topbar and workspace dock strings; regen docs map
Each inline link opens in its own tab (exact-URL dedupe); sidebar
target=_blank links open new tabs. Tab strip on top with click to
activate, close buttons, middle-click close, pointer-drag reorder, and
a per-tab context menu (Open in Default Browser, Copy Link, Reload,
Close Tab, Close Other Tabs). Navigation controls sit below the tabs
and follow the active tab. Closing the last tab collapses the sidebar
with no lingering webviews or history.
* feat(ui): drop the desktop top bar in favor of sidebar navigation
The Control UI top bar only rendered the OpenClaw › agent › page breadcrumb
on desktop, duplicating the sidebar. Desktop now renders no topbar row; the
row returns solely as the chat split toolbar's backdrop. Narrow viewports
keep the header (drawer toggle, brand, command-palette search) and now show
the brand across the whole drawer range. Routing already uses pushState, so
browser back/forward traverses navigation.
* feat(macos): add back/forward controls to the dashboard window
Native titlebar buttons next to the traffic lights drive WKWebView history,
which carries the Control UI's pushState navigation; enabled state tracks
canGoBack/canGoForward via KVO and trackpad swipe gestures are enabled too.
Back/forward traversals to entries from a replaced gateway endpoint cancel
silently instead of opening a dead URL in the system browser.
* fix(macos): keep the dashboard drag strip off the web content column
With the desktop topbar row removed, the 28px mid-window drag region sat on
top of the content column (chat thread has no top padding) and swallowed
clicks as window drags. Shrink it to a 12px edge strip; the sidebar region
over the reserved native-chrome padding stays the primary drag surface.
* fix(macos): follow gateway endpoint changes in the open Dashboard window
In remote SSH mode the Dashboard window baked the forwarded tunnel's
local port into the WebView URL and injected auth at open time; when
RemoteTunnelManager recreated the tunnel on a new ephemeral port the
open window reconnected to the dead port forever. DashboardManager now
subscribes to GatewayEndpointStore and, while the window is open,
re-injects auth for the new origin and reloads the WebView without
stealing focus. Dashboard log lines now strip the #token= fragment so
endpoint changes never write credentials to unified logs.
Fixes#100476
* test(macos): drop stale hasCrestodianSetupAuth assertions
OnboardingView.hasCrestodianSetupAuth was removed with the replaced
OnboardingView+CrestodianSetup source in #100288, leaving the macOS
test target failing to compile on main. Delete the test for the
removed internal helper.
Summary:
- The PR wires the macOS Dashboard and Canvas WKWebViews to WKUIDelegate and presents NSOpenPanel for HTML file inputs.
- PR surface: Other +61. Total +61 across 3 files.
- Reproducibility: yes. at source level: current main renders the affected file inputs while the macOS Dashboa ... fore-fix packaged macOS app in this read-only review, but the after-fix screenshots show the real app path.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 4f477c4ed0.
- Required merge gates passed before the squash merge.
Prepared head SHA: 4f477c4ed0
Review: https://github.com/openclaw/openclaw/pull/94612#issuecomment-4743165861
Co-authored-by: bbblending <li.mingkang@xydigit.com>