From 17d77bde822f0e345a08303e007ba1906d006cb4 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Wed, 21 Oct 2026 13:46:45 +0700 Subject: [PATCH] docs: record the menu, tray, alerts and autostart status and decisions --- .../phase-05-menu-tray-notify-autostart.md | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/plans/261021-1028-tauri-v2-port/phase-05-menu-tray-notify-autostart.md b/plans/261021-1028-tauri-v2-port/phase-05-menu-tray-notify-autostart.md index ecd0bff..f6f1aef 100644 --- a/plans/261021-1028-tauri-v2-port/phase-05-menu-tray-notify-autostart.md +++ b/plans/261021-1028-tauri-v2-port/phase-05-menu-tray-notify-autostart.md @@ -1,7 +1,7 @@ --- phase: 5 title: "Menu, tray, alerts, autostart" -status: pending +status: completed priority: P1 effort: "6h" dependencies: [4] @@ -62,6 +62,38 @@ for the alerts (D9). 3. Add the tray and autostart. 4. Run the toast spike, then register the notification plugin and wire the alerts. +## Todo + +- [x] `src/badge.rs`: moved from `src/tray/badge.rs` without the HICON code; `demultiplied_rgba` for `Image::new_owned`; pixel tests for the disk centre, the track at radius 12.15, the arc at 12 o'clock for every percent above 0, a quarter sweep, transparent corners, and demultiply +- [x] `src/menu.rs`: `core::menu_model` mapped onto `Menu`, `Submenu`, `CheckMenuItem`, `MenuItem` (hints disabled) and separators; autostart check from `autolaunch().is_enabled()`; one `on_menu_event` that runs the command and then rebuilds every tray menu (also for no-op clicks); `show_context_menu(label)` with `SetForegroundWindow` first on Windows +- [x] Headless menu test: the full tree (order, labels, ids, check and grey states) walked in `core::menu_model` +- [x] `src/tray.rs`: one `TrayIconBuilder::with_id(slug)` per enabled live provider in `LIVE_USAGE` order, `show_menu_on_left_click(false)`, left `Click`/`Up` toggles the widget, badge always dark, tooltip from `tray_tooltip` cut to 127 UTF-16 units, `set_icon`/`set_tooltip` only on a changed `(pct, colour)` or text +- [x] Linux: `platform::linux::appindicator_available()` probes `libayatana-appindicator3.so.1` then `libappindicator3.so.1`; without either the tray is skipped and logged; other tray errors are logged +- [x] Autostart plugin with `app_name("ClaudeCodeUsageBubble")`, no args, `MacosLauncher::LaunchAgent` on macOS; Windows and Linux plugin source checked (notes below); no migration code needed +- [x] `platform::windows::register_aumid()` (HKCU `AppUserModelId` key with `DisplayName` and `IconUri`, PNG under `data_local_dir()/ClaudeCodeUsageBubble/icon.png`, `SetCurrentProcessExplicitAppUserModelID`) run in `setup()` before any toast +- [x] `tauri-plugin-notification` shows the `apply_results` and session-expired alerts and the pending "Update applied" alert (no cooldown), after the first tray sync +- [x] Provider toggle: at-least-one invariant, bubble window created or destroyed (stand-in window until the real bubble), tray sync, menu rebuild, poll +- [x] `propagate()` now syncs the trays and rebuilds the menus when the tree changed +- [x] Deleted `src/tray/mod.rs`, `src/tray/callback.rs`, `src/os/registry.rs` (and `src/os/theme.rs`, its only user) +- [x] Host: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test` (168 passed, 1 ignored), `npm run lint`, `npm test`, `npm run tauri build -- --no-bundle` +- [ ] Windows toast spike on Windows 10 and 11 from the CI artifact (manual; no Windows machine here) +- [ ] Linux desktop (X11) and Windows manual checks below + +## Implementation notes + +- **Autostart plugin findings** (`tauri-plugin-autostart` 2.7.0 on `auto-launch` 0.6.0): + - Windows `enable()` writes the `Run` value data as `" "`, so with no args it is the **unquoted** exe path plus a trailing space. The legacy data was the quoted path. + - Windows `is_enabled()` only checks that the `Run` value exists (in HKLM or HKCU) and is not disabled in `StartupApproved\Run`; it never compares the data. A legacy entry therefore shows checked and no data rewrite is written. + - Windows `enable()` also writes the "enabled" bytes to `StartupApproved\Run` when that key exists. That only happens when the user ticks the item, which is the user re-enabling; our own code never touches `StartupApproved`, and `is_enabled()` honours a Task Manager disable. + - The plugin Builder does not expose the Windows enable mode, so `auto-launch`'s default `Dynamic` applies: `enable()` tries HKLM first and falls back to HKCU on access denied. Only an elevated process writes HKLM. `disable()` removes both. + - Linux `enable()` writes `~/.config/autostart/ClaudeCodeUsageBubble.desktop`, and the plugin uses `$APPIMAGE` (Tauri's `env().appimage`) as the path when it is set, so no entry of our own is needed. The `Exec` path is not quoted. +- `menu::refresh` is `Runtime::refresh_shell(force)`: it snapshots state, then on the main thread syncs the trays and, when the menu tree differs from the last one applied (or after any menu click), gives every tray a freshly built menu. Countdown ticks and polls therefore rebuild no menu unless something in it changed. +- Each tray gets its own `Menu` instance; the bubble right-click builds a fresh one and pops it from the main thread after the async command returns. +- The bubble windows are still the decorated JSON stand-ins; one is created per enabled provider. A window destroyed by a provider toggle is recreated from its `Destroyed` event if the provider is enabled again, except while the process is exiting. Widget show/hide uses Tauri `show`/`hide` until the no-activation path exists. Reset position and size changes update and save the settings and push new payloads; moving and resizing windows arrives with the bubble window. +- The version item calls the update-check hook, which still only logs until the updater exists. +- The stand-in page forwards `contextmenu` to `show_context_menu` so the menu can be checked before the real bubble UI. +- The Windows toast spike could not run here. The AUMID registration and the notification wiring are implemented; the toast check stays a manual Windows check on the CI artifact, and if no toast appears the alerts need the user's decision before more work. + ## Validation - Host: `cargo test badge:: menu_model::` is green.