improve: polish hub title bar, notifications, and chat UI - #1041
Conversation
Handle exact /new, /reset, and /compact commands through lifecycle RPCs, preserve structured compaction boundaries, and retain safe compatibility behavior for older gateways. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
Match the WinUI standard of pinning Settings to the very bottom of the navigation pane. Moves the Settings NavigationViewItem out of MenuItems into FooterMenuItems, placed after Diagnostics. Navigation still resolves via both collections and the high-contrast icon swap already covers footer items, so behavior is unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Drop the default button stroke and elevation depth from the three zero-state prompt suggestions (Say hi, What can you do?, Give me a quick tour of OpenClaw), keeping only a light, low-opacity fill at rest via SubtleFillColorSecondaryBrush. Rounded corners, padding, and hover feedback are unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The composer read as light gray on a dark chat surface and its fade gradient stayed white because FunctionalUI resolved theme brushes by walking the app-level ThemeDictionaries, which do not surface WinUI's XamlControlsResources framework brushes. Controls rendering dark fell back to the light Application.Resources snapshot. Fixes, using only built-in WinUI theme resources (no hardcoded colors, no C# theme helper): - App.xaml: re-declare the exact framework brush keys the chat uses in the Default/Light/HighContrast theme dictionaries, each aliasing its built-in color token via ThemeResource. Values are identical but now reachable by the per-theme walk, so they flip correctly. - FunctionalUI: resolve foreground/background/border resource brushes against the control's ActualTheme and re-apply reactively on ActualThemeChanged/Loaded so brushes flip on a runtime light/dark switch. - Composer: send/stop glyphs and fills, session-picker rows, and the welcome suggestion buttons resolve against ActualTheme instead of snapshotting the app theme; the fade gradient derives from the now-correct base-surface brush so it fades into the dock in dark. - Timeline: timestamp/helper captions resolve TextFillColorSecondary for the timeline root's ActualTheme so they stay legible in dark. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve explicit session selection and failed composer sends, retain live entries during authoritative reloads, widen compaction metrics, and clarify lifecycle timeout recovery. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
Merge the pane toggle into the lobster logo (hover reveals a DockLeft panel icon), move the back button to a chevron directly left of a centered search box, and give the title-bar icon buttons a subtle hover/pressed affordance. Make the right-side status/error pill transparent at rest (border kept for its dropdown) and the notification bell a true borderless subtle button. Convert the app notification banner to a native WinUI InfoBar with Title/Message and a standard ActionButton, and float it over the top-right of the content area (right ~2/5) so it never pushes the title bar or nav content down. Long messages wrap and grow the banner taller. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
ResolveColor threw InvalidOperationException when a raw WinUI color token was absent, which happens in minimal hosts (including the UI test surfaces) that seed only the paired '<key>Brush'. The chat timeline resolves TextFillColorSecondary during render, so the throw aborted the whole mount and the timeline rendered no ItemsRepeater, failing the chat proof tests. Fall back to the paired brush's color before throwing; both forms resolve to the same value in production. Adds a regression test covering the brush-color fallback and the still-missing-token throw. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…) lambdas Replace 7 repeated event subscriptions inside .Set() render paths with: - Theme.EnsureThemeCallback: ConditionalWeakTable-based single-subscription utility that stores and replaces the latest callback per control, invoking it immediately and on theme/load events (once, never accumulating). - FunctionalUI modifier path (.BackgroundResource / .Background(Ref(...))): for constant resource keys on Borders and Buttons, reuse the existing TrackThemedBrushes mechanism which already guards first-time subscription. - Control.Background support in ApplyModifiers + ReapplyThemedBrushes: the narrow renderer extension needed for Button backgrounds. Also remove the dead RootGrid Row 1 (formerly the InfoBar, now floating in Row 1 as an overlay). Regression tests prove: - 100 EnsureThemeCallback calls store exactly one callback (latest state) - FunctionalUI renderer applies BackgroundResource to Controls correctly Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 103120e9-d856-456c-885c-1ffd529b8746
The composer scrim derived its color by reading .Color off the framework
SolidBackgroundFillColorBaseBrush out of the visual tree, so its
{ThemeResource} re-resolved against the ambient light app theme and the
fade read white (#F3F3F3) on a dark page.
Add a dedicated ChatComposerFadeBrush to App.xaml ThemeDictionaries with
literal per-theme colors (dark #202020, light #F3F3F3, high-contrast
follows SystemColorWindowColor) and resolve it as a whole brush per
ElementTheme, so it flips correctly and stays aligned with the composer
dock fill. App-defined theme dictionaries are reachable by the
FunctionalUI theme walk; framework primitives are not.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Integrate openclaw#1040 demand-loaded history (LoadHistoryCoreAsync split, generation CTS, connection version guards) with PR openclaw#1036 authoritative reload path. Resolve provider conflicts preserving both connection-versioned history flights and authoritative reload pending queue. Address review findings: - Replace hardcoded 'New session' with localized Chat_PendingNewSessionTitle across all 5 locales (en-us, fr-fr, nl-nl, zh-cn, zh-tw) - Fix authoritative reload dropping valid live entries without OpenClawSeq when gateway clock skews behind local time: entries with no seq are now preserved since history coverage cannot be determined - Add post-timeout session list reconciliation for /new failures so user can see potentially-created sessions (protocol has no idempotency key; guidance message retained by design) - Add behavioral composer submission policy tests (reference equality, identity preservation, edit-during-send) - Add behavioral pending selection survival test for stale snapshots Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d2982ca8-bb56-4728-85bd-29542ce9d554
The _authoritativeHistoryReloadPending flag was consumed in LoadHistoryCoreAsync's finally block without checking whether the completing request belonged to the current connection generation. A stale old-generation completion after disconnect/reconnect could consume the flag and trigger an unintended authoritative reload in the newer generation. Fix: - Only consume/schedule the pending authoritative reload when requestConnectionVersion == _historyConnectionVersion (same guard as _historyInFlight removal) - Clear _authoritativeHistoryReloadPending in AdvanceHistoryGenerationLocked so generation advances invalidate stale pending flags - Add deterministic regression test: StaleGenerationAuthoritativeReload_DoesNotReloadInNewGeneration Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d2982ca8-bb56-4728-85bd-29542ce9d554
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f0e93ff-d320-454d-b00a-865dac727d0c
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: improve: polish hub title bar, notifications, and chat UI This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: improve: polish hub title bar, notifications, and chat UI This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
What Problem This Solves
The hub title bar and app notification banner did not match Windows 11 / GitHub Copilot app conventions ahead of the release. The pane toggle and logo were separate, the back button sat away from the search box, the right-side status and notification buttons had heavy resting fills, and the notification banner pushed the title bar and nav content down when it appeared.
Why This Change Was Made
Restyle the hub title bar into a single, familiar layout and convert the notification banner to a standard floating WinUI InfoBar so it overlays content instead of shifting it. This is UI-only polish; no behavior, capability, or data paths change.
User Impact
Evidence
Dark-mode isolated instance at PR head. The banner is shown in its Error state (expected "device token mismatch" in isolation), floating over the Connection page content:
Change Type
Scope
Validation (eb07b6c, integrated with main at 2fb1da2)
Run on Windows x64, Debug, at final integrated head:
./build.ps1- all 5 projects built successfully.dotnet test ./tests/OpenClaw.Shared.Tests- Passed: 3170, Failed: 0, Skipped: 31 (post-feat: handle lifecycle slash commands natively in Windows chat #1036 count confirmed).dotnet test ./tests/OpenClaw.Tray.Tests- Passed: 1916, Failed: 0 (post-feat: handle lifecycle slash commands natively in Windows chat #1036 count confirmed).dotnet test ./tests/OpenClaw.Tray.UITests(full suite, 2 runs) - Passed: 117/117 (run 1: 116+1 intermittent ChatPage ClickablePointOnScreen a11y timing; run 2: 117/117 clean; run 3: same intermittent. Pre-existing UIA timing issue, not caused by improve: polish hub title bar, notifications, and chat UI #1041).Handler accumulation regression tests (3/3 pass)
EnsureThemeCallback_100Renders_SingleStoredCallback: 100 render passes, single stored callback verifiedEnsureThemeCallback_LatestState_StoredCorrectly: latest per-render state captured correctlyTrackThemedBrushes_ControlBackground_ReRendersWithoutAccumulation: Button BackgroundResource modifier works through rendererReal Behavior Proof
run-app-local.ps1 -Isolated), dark theme../build.ps1; launch isolated; deep-linkopenclaw://hubto open the hub window.Security Impact
Compatibility and Migration
Review Conversations
Fix: Event Handler Accumulation (b3916e9)
Problem
7 sites in the chat components subscribed
ActualThemeChanged+Loadedinside.Set()lambdas that run on every render pass, causing linear handler accumulation per keystroke.Solution
Theme.EnsureThemeCallback(control, action): aConditionalWeakTable-based utility that subscribes once per control and stores/replaces the latest callback (invoked immediately and on theme/load events).ApplyModifiers+ReapplyThemedBrushesto handleControl.BackgroundResourceKey, so Buttons can use.BackgroundResource(...)for theme-tracked backgrounds.EnsureThemeCallback.Integration with #1036 (eb07b6c)
Merged origin/main (squashed #1036 at 2fb1da2) into PR branch. Auto-merged cleanly across overlapping chat files (ChatRoot, Timeline, Composer). Verified:
ActualThemeChanged +=in chat codeNon-blocking note
#1036's new compaction rows use the legacy
themeBrush()snapshot pattern (pre-existing in #1036, follow-up recommended to migrate toRef(...)).