Skip to content

Build the tray's menu as a model in the core - #986

Merged
SimonCropp merged 1 commit into
mainfrom
tray-menu-model
Oct 28, 2026
Merged

SimonCropp merged 1 commit into
mainfrom
tray-menu-model

Conversation

@SimonCropp

Copy link
Copy Markdown
Member

Phase 2c of the cross-platform tray plan: the tray's menu becomes a model in the core, snapshot tested as text, and the Windows head only draws it.

TrayMenu (core) builds PlatformHeads' TrayMenuItems from what the tracker holds, with an action for each item:

  • Each item's id names the entry it acts on by that entry's key: a move's received file, a delete's file, a snapshot's key. A click from a menu built before a change acts on that entry or on nothing, never on whatever came to sit in its place.
  • Two halves, Fixed and Tracked, because the Windows head keeps the fixed items and builds the tracked ones each time the menu opens.
  • What only a head can do is handed in as TrayActions: its windows, exit, and starting a move's diff tool.
  • Tips are kept beside the items rather than in TrayMenuItem, since a Linux tray's menu has nowhere to show one.

MenuBuilder (Windows head) makes the model ToolStrip items with PlatformHeads' TrayMenuItems, which BuildMonitor's tray uses too, and sets the tips and the submenus' direction through the options' Style. MenuButton is gone.

Two visible changes:

  • Each file and snapshot entry is an ordinary submenu item, with an arrow on the right, that opens on hover. It was a drop-down button that opened on click.
  • The solution heading is greyed out. A menu built from a model has no "shown but not selectable" item, and an item that does nothing when chosen is a trap on any platform's menu.

The Windows head keeps its own NotifyIcon and ContextMenuStrip rather than moving to PlatformHeads' NotifyIconTray. The tray is event driven, its hot keys register on the icon's window, and a left click opens the menu, where NotifyIconTray is built for a polling loop. That's a question for phase 3.

docs/tray.md said clicking a file accepts it, which the drop-down buttons didn't do either. Those lines now describe the submenus.

Tests:

  • TrayMenuTests (core) snapshots the menu as text, and checks that ids are unique, that each half answers only for its own items, and that "Open diff tool" is handed the move as it is when chosen.
  • MenuBuilderTest (head) keeps the Empty, Full, FullGrouped and drop-down images, and tests the tips, a click through both halves, menus kept off the desktop, and disposal. The other six images are covered by the text snapshots.
  • Windows: the full solution in Release passes (3,760 tests). Linux, in a dotnet/sdk:10.0 container: the core's 272 tests pass, 43 of them skipped as Windows only.

TrayMenu builds PlatformHeads' TrayMenuItems from what the tracker holds,
with an action for each by id and tips kept beside the items. Ids name the
entry acted on by its key. It comes in two halves, Fixed and Tracked, and
what only a head can do is handed in as TrayActions.

The Windows head's MenuBuilder makes the model ToolStrip items with
PlatformHeads' TrayMenuItems, keeping the fixed items and building the
tracked ones on every open. MenuButton goes.

TrayMenuTests in the core's tests snapshot the menu as text and run on
every platform; MenuBuilderTest keeps four images and the head's own tests.
@SimonCropp
SimonCropp merged commit be3ce20 into main Oct 28, 2026
12 checks passed
@SimonCropp
SimonCropp deleted the tray-menu-model branch October 28, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant