Files
clash-verge-rev/src-tauri/src/core/notify/desktop.rs
T
Tunglies 8328e34208 refactor(backend): declarative effects (#8128)
* refactor(core): type notice statuses behind the frozen wire contract

* refactor(utils): unified retry and strategy-list helpers

* refactor(feat): declarative effect registry for verge and clash patches

* refactor(core): derive refresh announcements from transaction commit

* refactor(core): fold tray, hotkey, autostart updates into effect ensures

* refactor(utils): migrate remaining bounded retry loops

* docs: add src-tauri architecture guardrails

* refactor(core): coalesce burst refresh announcements

* refactor(core): complete bounded service retry migration

* ci(backend): add architecture ban gates

* test(feat): freeze representative effect registry mappings

* docs(backend): record dead wire contract entries

* chore(core): document watcher exit conditions

* fix(backend): preserve applied state across later failures

* fix(config): retain runtime after an applied core replacement

* refactor(backend): flatten refresh publication and retry policies

* docs(backend): focus guardrails on architecture ownership

* refactor(effects): use one execution order

* fix(config): publish retained runtime and reconcile proxy settings
2026-10-07 07:38:55 +00:00

98 lines
3.8 KiB
Rust

use std::borrow::Cow;
use crate::{core::handle, utils::window_manager::WindowState};
use clash_verge_i18n;
use tauri_plugin_notification::NotificationExt as _;
pub enum NotificationEvent<'a> {
DashboardToggled,
ClashModeChanged {
mode: &'a str,
},
SystemProxyToggled(bool),
/// A proxy change failed while no window could report it.
SystemProxyFailed,
/// The system proxy guard stopped.
SystemProxyGuardStopped,
TunModeToggled(bool),
LightweightModeEntered,
ProfilesReactivated,
AppQuit,
}
/// Whether no app window can currently show the failure.
pub const fn needs_system_notification(state: WindowState) -> bool {
match state {
WindowState::Hidden | WindowState::Minimized | WindowState::NotExist => true,
WindowState::VisibleFocused | WindowState::VisibleUnfocused => false,
}
}
fn notify(title: Cow<'_, str>, body: Cow<'_, str>) {
let app_handle = handle::Handle::app_handle();
app_handle.notification().builder().title(title).body(body).show().ok();
}
pub async fn notify_event<'a>(event: NotificationEvent<'a>) {
match event {
NotificationEvent::DashboardToggled => {
let title = clash_verge_i18n::t!("notifications.dashboardToggled.title");
let body = clash_verge_i18n::t!("notifications.dashboardToggled.body");
notify(title, body);
}
NotificationEvent::ClashModeChanged { mode } => {
let title = clash_verge_i18n::t!("notifications.clashModeChanged.title");
let body = clash_verge_i18n::t!("notifications.clashModeChanged.body")
.replace("{mode}", mode)
.into();
notify(title, body);
}
NotificationEvent::SystemProxyToggled(enabled) => {
let title = clash_verge_i18n::t!("notifications.systemProxyToggled.title");
let key = if enabled {
"notifications.systemProxyToggled.on"
} else {
"notifications.systemProxyToggled.off"
};
let body = clash_verge_i18n::t!(key);
notify(title, body);
}
NotificationEvent::SystemProxyFailed => {
let title = clash_verge_i18n::t!("notifications.systemProxyFailed.title");
let body = clash_verge_i18n::t!("notifications.systemProxyFailed.body");
notify(title, body);
}
NotificationEvent::SystemProxyGuardStopped => {
let title = clash_verge_i18n::t!("notifications.systemProxyGuardStopped.title");
let body = clash_verge_i18n::t!("notifications.systemProxyGuardStopped.body");
notify(title, body);
}
NotificationEvent::TunModeToggled(enabled) => {
let title = clash_verge_i18n::t!("notifications.tunModeToggled.title");
let key = if enabled {
"notifications.tunModeToggled.on"
} else {
"notifications.tunModeToggled.off"
};
let body = clash_verge_i18n::t!(key);
notify(title, body);
}
NotificationEvent::LightweightModeEntered => {
let title = clash_verge_i18n::t!("notifications.lightweightModeEntered.title");
let body = clash_verge_i18n::t!("notifications.lightweightModeEntered.body");
notify(title, body);
}
NotificationEvent::ProfilesReactivated => {
let title = clash_verge_i18n::t!("notifications.profilesReactivated.title");
let body = clash_verge_i18n::t!("notifications.profilesReactivated.body");
notify(title, body);
}
NotificationEvent::AppQuit => {
let title = clash_verge_i18n::t!("notifications.appQuit.title");
let body = clash_verge_i18n::t!("notifications.appQuit.body");
notify(title, body);
}
}
}