Files
Windows-Gotify-Client-Rust/src/config.rs
T
KennethCheng 2614909c4c feat(windows): Phase 7 C1 — 托盘菜单增强 + 单实例激活现有窗口
- 托盘菜单加 4 项:New messages: N(灰)/ Pause notifications(勾选态)/ Settings.../ Restart connection
- 单实例:第二次启动通过 RegisterWindowMessageW 发激活请求,托盘 WndProc 收后调用 on_open(show+reset counter);main.rs AlreadyRunning 路径调用 activate_existing_instance
- AppConfig 加 notifications_paused 字段(与 desktop_notifications 区分,tray 暂停持久化)
- WS drain 通过 Rc<RefCell<Option<Arc<TrayState>>>> 与托盘共享 new_messages 计数器
- WndProc 在调用 on_open 前自己清零计数器,免去回调侧的 RefCell 捕获(保持 Send+Sync)
2026-09-19 08:13:42 +08:00

68 lines
2.4 KiB
Rust

//! Active-config view used at runtime.
//!
//! Phase 5 C1: this is a thin wrapper over `storage::AppConfig`. It
//! surfaces the single selected server as `ServerConfig` so the rest
//! of the runtime (`gotify::GotifyApi`, `gotify::websocket`) doesn't
//! have to care about the multi-server storage layout. The placeholder
//! URL/token that lived here in Phase 3 C2 is gone — first-run users
//! will see "no server configured" until they fill in Settings
//! (Phase 6 hooks up the Settings → Connection form).
use crate::error::AppResult;
use crate::gotify::ServerConfig;
use crate::storage::AppConfig as PersistedConfig;
pub struct ActiveConfig {
pub server: Option<ServerConfig>,
pub appearance: String,
pub desktop_notifications: bool,
pub sound: bool,
pub notify_high: bool,
pub notify_max: bool,
pub notifications_paused: bool,
pub start_with_windows: bool,
pub start_minimized: bool,
pub close_to_tray: bool,
}
impl ActiveConfig {
/// Load from `%APPDATA%/WindowsGotify/config.json` (or defaults on
/// missing / malformed file). Returns `Ok(ActiveConfig)` even when
/// there's no server configured — the caller decides how to
/// surface that in the UI.
pub fn load() -> AppResult<Self> {
let persisted = crate::storage::load_config();
Ok(Self::from_persisted(persisted))
}
fn from_persisted(p: PersistedConfig) -> Self {
let server = p
.active_server()
.or_else(|| p.first_enabled_server())
.map(|entry| entry.config.clone());
Self {
server,
appearance: p.appearance,
desktop_notifications: p.desktop_notifications,
sound: p.sound,
notify_high: p.notify_high,
notify_max: p.notify_max,
notifications_paused: p.notifications_paused,
start_with_windows: p.start_with_windows,
start_minimized: p.start_minimized,
close_to_tray: p.close_to_tray,
}
}
/// Build an `ActiveConfig` from a fully-formed `PersistedConfig`
/// value (handy for tests and for the upcoming Settings → Save
/// path, which constructs the persisted config in memory and then
/// asks us to mirror it back).
pub fn from_persisted_value(p: PersistedConfig) -> Self {
Self::from_persisted(p)
}
pub fn placeholder() -> Self {
Self::from_persisted(PersistedConfig::default())
}
}