refactor: extract tray menu builder out of App.xaml.cs#412
Merged
shanselman merged 12 commits intoMay 16, 2026
Conversation
… lines) Move all Build* tray menu helpers into TrayMenuStateBuilder, backed by an immutable TrayMenuSnapshot captured under lock before each rebuild. App.xaml.cs delegates entirely via CaptureTrayMenuSnapshot() + builder.Build(). Also adds a self-marshal guard to UpdateTrayIcon() so gateway/node callbacks are safe to call from any thread without a separate OnUiThread wrapper. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four TrayMenuPopupCompositionTests read App.xaml.cs and checked for method names and section markers that now live in TrayMenuStateBuilder.cs after the builder extraction. Point them at the new file; RoutesAboutAction splits across both (menu emission in builder, case handler in App). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
App.xaml.cshad grown to include about 1,300 lines of tray menupresentation logic — all the
Build*helpers, flyout constructors, andthe coordinator that wired them together. This moves that block into a
dedicated
TrayMenuStateBuilderclass backed by an immutableTrayMenuSnapshotrecord, following the same pattern already establishedby
CommandCenterStateBuilder.App.xaml.csno longer owns any tray rendering logic. It captures asnapshot of the relevant state before each rebuild and hands it to the
builder alongside two callbacks (dispatch action, save-and-reconnect).
What changed
Services/TrayMenuSnapshot.cs— immutable record with the 18 fieldsthe builder needs (connection status, sessions, usage, node state, etc.)
Services/TrayMenuStateBuilder.cs— allBuild*methods moved here;_last*field references replaced with snapshot fieldsApp.xaml.cs—BuildTrayMenuPopupnow captures the snapshot anddelegates to the builder;
BuildTrayMenuPopupCoreand all helpersremoved;
TruncateMenuTextdead code removedUpdateTrayIcon— added a self-marshal guard so gateway and nodecallbacks can safely call it from any thread
Testing
dotnet build src/OpenClaw.Tray.WinUI -r win-x64— 0 errorstray-menu-builder-demo.mp4
Notes
This is a zero-behavior-change refactor. The rendered menu is identical;
the only observable difference is
UpdateTrayIconnow re-dispatches tothe UI thread if called off-thread instead of assuming thread affinity.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com