Skip to content

Menu bar: a Hidden style that takes the item off the menu bar - #297

Merged
fylorn merged 1 commit into
devfrom
feat/menubar-off
Oct 9, 2026
Merged

fylorn merged 1 commit into
devfrom
feat/menubar-off

Conversation

@fylorn

@fylorn fylorn commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

What

Settings › General › Menu bar gets a fourth choice, Hidden (不显示), next to Icon and numbers / Icon only / Numbers only. It removes ThinkWatch Lite's item from the menu bar, at once and without a restart; picking another style brings it back with the same menu.

How

  • menubar::model::Style::Hidden (serde "hidden", atomic 3); MenubarStyle in src/settings/api.ts gains "hidden".
  • macOS (menubar/macos.rs): the NSStatusItem is now created lazily by apply and removed with NSStatusBar.removeStatusItem by hide; the NSMenu and its delegate stay, and are attached to the new item when it comes back. Started with Hidden, no item is created at all.
    • Not setVisible(false): AppKit persists it under the autosave name (NSStatusItem VisibleCC ThinkWatchLite = 0, checked with a probe), so the next launch would start hidden and an older version, which never sets it back, would keep the item hidden for good. removeStatusItem persists nothing.
  • While hidden, the menu bar loop asks core for nothing (no /summary, /quota, ChatGPT reset credits); menubar_now, already notified by set_menubar_style, wakes it when the style changes.

Getting back to the app with the item hidden

Nothing changes in the window/activation code: closing the main window still turns the app into an accessory app (no Dock icon). Opening ThinkWatch Lite again from Finder, Spotlight or open reaches the running instance as applicationShouldHandleReopen → RunEvent::Reopen, which already calls show_main_window (which makes the app Regular again). I checked that an Accessory-policy app does receive the reopen event (probe app bundle, opened twice), and ran the real app isolated (below). Notifications (clicks open the window), auto-update (its own window), ⌘Q from the main window and deep links are untouched.

The row's note becomes "To show the main window, open ThinkWatch Lite again from Finder or Spotlight." while Hidden is selected (instead of a one-time pop-up, it stays where someone would look for it). The launch-at-login note and the first-autostart notice say the app runs in the background instead of "only the icon appears in the menu bar".

Windows / Linux

Unchanged and still macOS-only, like the other styles: the row is only shown on macOS and drawn_style() keeps drawing the tray icon there whatever is stored. Hiding the tray icon would leave relaunching as the only way in, and on Linux that depends on the desktop (activation tokens, AppIndicator); Windows already lets users hide notification-area icons itself.

Verification

  • pnpm typecheck, pnpm test (932), pnpm build, cargo fmt --check, cargo clippy --all-targets -D warnings, cargo test (901, incl. control_plane against twcore v0.65.0).
  • New tests: the style round-trips (all four) and only macOS draws Hidden; prefs store it as "hidden".
  • Shared menubar code (model + style/set_style/drawn_style + the hidden branch of the loop) extracted into a throwaway crate: clippy --all-targets -D warnings clean for x86_64/aarch64-pc-windows-msvc and x86_64-unknown-linux-gnu.
  • Isolated real app on macOS 26 (debug build with its own bundle id, own data dir, own gateway port; scripted through the real set_menubar_style IPC): started Hidden → no status item; window closed → Accessory policy, no window; open the bundle again → window shown, Regular; Icon and numbers → item back with its menu attached, and a click opens the menu; Hidden again → gone; Icon only → back. Prefs file follows each change, and no NSStatusItem Visible… key was written.
  • Preview harness: Settings › General in zh/en, light/dark, 1100 and 820 wide; picking Hidden swaps both notes and back.

🤖 Generated with Claude Code

Settings > General > Menu bar gets a fourth choice next to icon and
numbers / icon only / numbers only. It takes effect at once: the
NSStatusItem is removed with removeStatusItem and a new one is created,
with the same menu, when another style is picked. setVisible(false) is
not used because AppKit persists it under the autosave name, so the item
would start hidden on the next launch and stay hidden in an older version
that does not know this style. While hidden, the menu bar loop asks core
for nothing until the style changes.

With the item hidden and the window closed the app stays an accessory
app (no Dock icon): opening it again from Finder, Spotlight or `open`
reaches the running instance as RunEvent::Reopen, which already shows the
main window. Choosing Hidden swaps the row's note for how to get back to
the window, the launch-at-login note and the first-autostart notice say
it runs in the background.

macOS only, like the other styles: elsewhere the stored value still draws
the tray icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fylorn
fylorn merged commit 543674e into dev Oct 9, 2026
4 checks passed
@fylorn
fylorn deleted the feat/menubar-off branch October 9, 2026 03:21
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.

1 participant