3.5 KiB
System Tray Implementation (v0.2.0)
Goal: Replace the CMD window with a system tray icon. Users interact via tray menu: "Open in Browser" or "Quit". No console window on Windows.
Overview
- Scope: Single codebase, cross-platform. CI/CD unchanged—same build pipeline produces one binary per OS.
- Complexity: Low–medium. Uses a cross-platform Rust crate; platform-specific code is minimal.
Implementation Steps
1. Add Tray Crate Dependency
Add to backend/Cargo.toml:
# System tray (production mode)
tray-item = "0.10"
Alternative: tray-icon (more features, heavier; requires event loop integration).
2. Windows: Hide Console Window
Add near the top of backend/src/main.rs (after mod declarations if any, before fn main):
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
- Debug builds: Console remains (for logs).
- Release builds: No CMD window on Windows.
3. Remove Auto-Open Browser on Startup
In main.rs, remove or conditionally disable the auto-open logic (the tokio::spawn block that calls webbrowser::open()). The user will open the browser from the tray menu instead.
4. Add Tray Icon and Menu (Production Mode Only)
When has_frontend is true (production mode):
- Create tray icon with an appropriate icon (or placeholder).
- Add menu items:
- "Open in Browser" — calls
webbrowser::open()withhttp://localhost:{port}. - "Quit" — shuts down the server and exits the process.
- "Open in Browser" — calls
5. Threading Considerations
- macOS: Some tray crates expect event handling on the main thread. May need to run tray logic on main thread and spawn the Axum server on a background thread, or use crate-specific patterns.
- Windows/Linux: Usually more flexible; verify with the chosen crate’s docs.
6. CI/CD Changes (If Needed)
Current release.yml builds for Windows, macOS, and Linux. Likely no changes required.
If using a crate that needs GTK on Linux (e.g. tray-icon), add to the "Install system dependencies (Linux)" step:
sudo apt-get install -y cmake libgtk-3-dev libappindicator3-dev
Note: Linux users would then need GTK installed at runtime. For tray-item, check whether it has different Linux deps.
Behaviour Summary
| Before (v0.1.0) | After (v0.2.0) |
|---|---|
| CMD window visible | No console window (Windows) |
| Browser opens on start | Browser opens via tray menu |
| Quit via Ctrl+C | Quit via tray menu |
Testing Checklist
- Windows: No CMD window when running release binary.
- Windows: Tray icon appears; "Open in Browser" opens correct URL.
- Windows: "Quit" exits cleanly.
- macOS: Tray icon in menu bar; menu works.
- Linux: Tray icon in system tray; menu works.
- Development mode (
cargo run): Behaviour unchanged (no tray, API-only).
Icon Asset
You’ll need a tray icon (e.g. 16×16 or 32×32 PNG). Options:
- Extract from existing branding/logo.
- Use a simple placeholder (e.g. filled circle) for initial implementation.
- Store in
backend/orbackend/static/and load at runtime.
References
- tray-item crate
- tray-icon crate (alternative)
#![windows_subsystem = "windows"]— Rust embed documentation