unistore_tray/
lib.rs

1//! # unistore-tray
2//!
3//! 跨平台系统托盘能力 - UniStore 能力生态的一部分。
4//!
5//! ## 功能特性
6//!
7//! - **跨平台**: 支持 Windows/macOS/Linux
8//! - **统一 API**: 屏蔽平台差异,提供一致的接口
9//! - **异步友好**: 与 tokio 运行时无缝集成
10//! - **事件驱动**: 通过 broadcast channel 订阅托盘事件
11//! - **可扩展菜单**: 灵活的菜单构建器 API
12//!
13//! ## 快速开始
14//!
15//! ```rust,no_run
16//! use unistore_tray::{SystemTray, TrayConfig, TrayEvent, MenuBuilder};
17//!
18//! #[tokio::main]
19//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
20//!     // 创建托盘配置
21//!     let config = TrayConfig::builder()
22//!         .tooltip("My App v1.0")
23//!         .build();
24//!
25//!     // 创建系统托盘(需要在主线程)
26//!     let tray = SystemTray::new(config)?;
27//!
28//!     // 设置菜单
29//!     let menu = MenuBuilder::new()
30//!         .item("open", "打开主窗口")
31//!         .separator()
32//!         .item("exit", "退出")
33//!         .build();
34//!     tray.set_menu(menu)?;
35//!
36//!     // 订阅事件
37//!     let mut rx = tray.subscribe();
38//!     
39//!     // 事件处理循环
40//!     while let Ok(event) = rx.recv().await {
41//!         match event {
42//!             TrayEvent::MenuItemClicked(id) if id.as_str() == "exit" => break,
43//!             _ => {}
44//!         }
45//!     }
46//!
47//!     Ok(())
48//! }
49//! ```
50
51mod deps;
52mod error;
53mod config;
54mod event;
55mod icon;
56mod menu;
57mod tray;
58mod backend;
59
60// 公开导出
61pub use error::{TrayError, TrayResult};
62pub use config::{TrayConfig, TrayConfigBuilder};
63pub use event::{TrayEvent, MenuItemId};
64pub use icon::TrayIcon;
65pub use menu::{Menu, MenuItem, MenuBuilder};
66pub use tray::SystemTray;
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn test_config_builder() {
74        let config = TrayConfig::builder()
75            .tooltip("Test App")
76            .event_channel_capacity(128)
77            .build();
78        
79        assert_eq!(config.tooltip, "Test App");
80        assert_eq!(config.event_channel_capacity, 128);
81    }
82
83    #[test]
84    fn test_menu_builder() {
85        let menu = MenuBuilder::new()
86            .item("open", "打开")
87            .separator()
88            .check_item("auto_start", "开机启动", true)
89            .item("exit", "退出")
90            .build();
91        
92        assert_eq!(menu.items().len(), 4);
93    }
94
95    #[test]
96    fn test_menu_item_id() {
97        let id1: MenuItemId = "test".into();
98        let id2 = MenuItemId::new("test");
99        assert_eq!(id1, id2);
100        assert_eq!(id1.as_str(), "test");
101    }
102
103    #[test]
104    fn test_tray_event_debug() {
105        let event = TrayEvent::Click;
106        assert!(format!("{:?}", event).contains("Click"));
107        
108        let event = TrayEvent::MenuItemClicked(MenuItemId::new("exit"));
109        assert!(format!("{:?}", event).contains("exit"));
110    }
111}