feat: add native macOS tray renderer#1440
Conversation
Introduce a TraySurface abstraction so macOS can use an AppKit-backed status item while other platforms keep the Tauri tray implementation. Render CPU/GPU metrics with native icons, keep the app logo visible, and tint the SVG logo as a template image. Add focused tray widget and macOS surface tests. Validation: cargo test -p hardware_visualizer tray::; cargo clippy -p hardware_visualizer --all-targets.
📝 WalkthroughWalkthroughThis PR introduces a ChangesTray Surface Abstraction & macOS Native Implementation
Sequence DiagramsequenceDiagram
participant Widget as Tray Widget
participant Adapter as TrayAdapter
participant Surface as TraySurface (Abstract)
participant Platform as Platform Impl
participant Native as macOS AppKit / Tauri API
Widget->>Adapter: next_frame (TrayFrame with metrics)
Adapter->>Surface: apply_frame(&frame)
alt macOS Implementation
Surface->>Platform: MacosTraySurface::apply_frame
Platform->>Platform: Build attributed title<br/>(logo + metric icons)
Platform->>Native: run_on_main_thread()
Native->>Native: Update NSStatusItem title/tooltip
Native-->>Platform: Scheduled & executed
else Tauri Fallback
Surface->>Platform: TauriTraySurface::apply_frame
Platform->>Native: Update tray icon title/tooltip
Native-->>Platform: Updated
end
Platform-->>Surface: Frame applied
Surface-->>Adapter: Complete
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly Related PRs
Suggested Labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 4/5 reviews remaining, refill in 12 minutes. Comment |
Rust Tauri Coverage ReportCoverage Details |
There was a problem hiding this comment.
Pull request overview
Adds a platform-swappable tray rendering abstraction to support a native AppKit-backed macOS tray/widget surface while keeping the existing Tauri tray implementation for non-macOS platforms.
Changes:
- Introduces
TraySurfaceand moves the existing Tauri tray implementation behind it (non-macOS). - Implements a native macOS
NSStatusItemsurface that renders an attributed title with a template-tinted app logo + metric icons/values. - Extends tray frame modeling to include per-metric icon metadata and adds focused unit tests.
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src-tauri/src/tray/widget.rs | Extends TrayFrame with items (icon/value/state) and updates frame building + tests. |
| src-tauri/src/tray/surface/mod.rs | Defines TraySurface trait and factory selecting macOS vs non-macOS implementation. |
| src-tauri/src/tray/surface/tauri_surface.rs | New non-macOS tray surface using Tauri tray APIs (menu + title/tooltip updates). |
| src-tauri/src/tray/surface/macos.rs | New native AppKit tray surface using NSStatusItem + attributed title rendering and tests. |
| src-tauri/src/tray/mod.rs | Exposes new tray::surface module. |
| src-tauri/src/adapters/tray.rs | Refactors adapter to drive a TraySurface instead of owning TrayIcon directly. |
| src-tauri/Cargo.toml | Adds macOS-only objc2* dependencies required for AppKit implementation. |
| assets/hv-icon-outline.svg | Adds outline logo SVG used for template-tinted menu bar rendering. |
| Cargo.lock | Locks new macOS dependency graph. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src-tauri/src/tray/widget.rs (1)
306-324: Use valid SF Symbol names for metric icons. The symbols "cpu" and "display" are not valid SF Symbols in any macOS version; "thermometer" requires macOS 13.0+. The code gracefully falls back to text labels when symbols are unavailable, but for better UX, consider using alternative valid symbols: "cpu.fill" or "gear" for CPU, "display" could use "desktopcomputer" or "macbook", and "thermometer" is valid but dependent on macOS minimum version support. The fallback mechanism ensures no runtime errors, but using valid symbol names will display icons instead of text labels.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src-tauri/src/tray/widget.rs` around lines 306 - 324, Replace invalid SF Symbol names in metric_icon_config so macOS shows icons instead of fallback text: for TrayMetric::Cpu set macos_symbol_name to a valid symbol such as "cpu.fill" or "gear"; for TrayMetric::Gpu set macos_symbol_name to a valid symbol such as "desktopcomputer" or "macbook"; for TrayMetric::Temp either keep "thermometer" only if macOS deployment target supports it or use a more widely available alternative like "thermometer.sun" or "thermometer.medium". Update the macos_symbol_name fields on the TrayMetricIcon values in metric_icon_config accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src-tauri/src/tray/widget.rs`:
- Around line 306-324: Replace invalid SF Symbol names in metric_icon_config so
macOS shows icons instead of fallback text: for TrayMetric::Cpu set
macos_symbol_name to a valid symbol such as "cpu.fill" or "gear"; for
TrayMetric::Gpu set macos_symbol_name to a valid symbol such as
"desktopcomputer" or "macbook"; for TrayMetric::Temp either keep "thermometer"
only if macOS deployment target supports it or use a more widely available
alternative like "thermometer.sun" or "thermometer.medium". Update the
macos_symbol_name fields on the TrayMetricIcon values in metric_icon_config
accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: ef9299bf-03d5-4314-ac83-75ca20115034
⛔ Files ignored due to path filters (2)
Cargo.lockis excluded by!**/*.lockassets/hv-icon-outline.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
src-tauri/Cargo.tomlsrc-tauri/src/adapters/tray.rssrc-tauri/src/tray/mod.rssrc-tauri/src/tray/surface/macos.rssrc-tauri/src/tray/surface/mod.rssrc-tauri/src/tray/surface/tauri_surface.rssrc-tauri/src/tray/widget.rs
Summary
TraySurfaceabstraction so platform-specific tray renderers can be swapped independently.NSColor::labelColor().Related Issues
Refs #1401
Type of Change
fix/branch)feat/branch)refactor/branch)docs/branch)chore/branch)Screenshots / Videos
N/A
Test Plan
Commands run:
cargo test -p hardware_visualizer tray:: cargo clippy -p hardware_visualizer --all-targetsChecklist
npm run lint && npm run format/cargo tauri-lint && cargo tauri-fmt)npm test/cargo tauri-test)Summary by CodeRabbit
Release Notes