Skip to content

refactor: extract tray menu builder out of App.xaml.cs#412

Merged
shanselman merged 12 commits into
openclaw:masterfrom
AlexAlves87:refactor/extract-tray-menu-builder
May 16, 2026
Merged

refactor: extract tray menu builder out of App.xaml.cs#412
shanselman merged 12 commits into
openclaw:masterfrom
AlexAlves87:refactor/extract-tray-menu-builder

Conversation

@AlexAlves87
Copy link
Copy Markdown
Contributor

@AlexAlves87 AlexAlves87 commented May 15, 2026

Summary

App.xaml.cs had grown to include about 1,300 lines of tray menu
presentation logic — all the Build* helpers, flyout constructors, and
the coordinator that wired them together. This moves that block into a
dedicated TrayMenuStateBuilder class backed by an immutable
TrayMenuSnapshot record, following the same pattern already established
by CommandCenterStateBuilder.

App.xaml.cs no longer owns any tray rendering logic. It captures a
snapshot 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 fields
    the builder needs (connection status, sessions, usage, node state, etc.)
  • Services/TrayMenuStateBuilder.cs — all Build* methods moved here;
    _last* field references replaced with snapshot fields
  • App.xaml.csBuildTrayMenuPopup now captures the snapshot and
    delegates to the builder; BuildTrayMenuPopupCore and all helpers
    removed; TruncateMenuText dead code removed
  • UpdateTrayIcon — added a self-marshal guard so gateway and node
    callbacks can safely call it from any thread

Testing

  • dotnet build src/OpenClaw.Tray.WinUI -r win-x64 — 0 errors
  • Manual: right-click tray, all flyouts, permission toggles, disconnect/reconnect, Canvas, Dashboard, Chat — all working as before
tray-menu-builder-demo.mp4

Notes

This is a zero-behavior-change refactor. The rendered menu is identical;
the only observable difference is UpdateTrayIcon now re-dispatches to
the UI thread if called off-thread instead of assuming thread affinity.

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

AlexAlves87 and others added 12 commits April 8, 2026 16:34
… 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>
@shanselman shanselman merged commit 33b537e into openclaw:master May 16, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants