mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-08 02:52:07 +08:00
refactor(core): type notice statuses behind the frozen wire contract
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use crate::core::notify::NoticeStatus;
|
||||
use crate::{config::with_encryption, process::AsyncHandler};
|
||||
use anyhow::{Context as _, Result, anyhow, bail};
|
||||
use clash_verge_logging::{Type, logging};
|
||||
@@ -58,7 +59,7 @@ fn parse_mapping(yaml_str: String, path: PathBuf) -> Result<Mapping> {
|
||||
let error_msg = format!("YAML syntax error in {}: {}", path.display(), err);
|
||||
logging!(error, Type::Config, "{}", error_msg);
|
||||
|
||||
crate::core::handle::Handle::notice_message("config_validate::yaml_syntax_error", &error_msg);
|
||||
crate::core::handle::Handle::notice(NoticeStatus::ConfigValidateYamlSyntaxError, error_msg.as_str());
|
||||
|
||||
bail!("YAML syntax error: {}", err)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ pub mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos_launch_guard;
|
||||
pub(crate) mod network;
|
||||
pub mod notification;
|
||||
pub use crate::core::notify::desktop as notification;
|
||||
pub mod port;
|
||||
pub mod resolve;
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::core::notify::NoticeStatus;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use anyhow::Result;
|
||||
@@ -223,7 +224,7 @@ async fn init_core_manager() -> bool {
|
||||
Err(error) => {
|
||||
logging!(error, Type::Setup, "core manager initialization failed: {error:#}");
|
||||
CoreManager::global().record_startup_error(CoreFailure::StartFailed(format!("{error:#}")));
|
||||
Handle::notice_message("core_start::error", "");
|
||||
Handle::notice(NoticeStatus::CoreStartError, "");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::core::notify::NoticeStatus;
|
||||
use anyhow::Result;
|
||||
use percent_encoding::percent_decode_str;
|
||||
use smartstring::alias::String;
|
||||
@@ -93,18 +94,18 @@ async fn import_subscription(url: &str, name: Option<&String>) {
|
||||
if let Err(e) = profiles::profiles_append_item_safe(&mut item).await {
|
||||
logging!(error, Type::Config, "failed to import subscription url: {:?}", e);
|
||||
Config::profiles().await.discard();
|
||||
handle::Handle::notice_message("import_sub_url::error", e.to_string());
|
||||
handle::Handle::notice(NoticeStatus::ImportSubUrlError, e.to_string());
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(e) = profiles::profiles_save_file_safe().await {
|
||||
logging!(error, Type::Config, "failed to save imported subscription: {e:#}");
|
||||
handle::Handle::notice_message("import_sub_url::error", e.to_string());
|
||||
handle::Handle::notice(NoticeStatus::ImportSubUrlError, e.to_string());
|
||||
return;
|
||||
}
|
||||
logging_error!(Type::Timer, Timer::global().refresh().await);
|
||||
handle::Handle::notice_message(
|
||||
"import_sub_url::ok",
|
||||
handle::Handle::notice(
|
||||
NoticeStatus::ImportSubUrlOk,
|
||||
"", // 空 msg 传入,我们不希望导致 后端-前端-后端 死循环,这里只做提醒。
|
||||
);
|
||||
|
||||
@@ -116,7 +117,7 @@ async fn fetch_profile_item(url: &str, name: Option<&String>) -> Option<PrfItem>
|
||||
Ok(item) => Some(item),
|
||||
Err(e) => {
|
||||
logging!(error, Type::Config, "failed to parse profile from url: {:?}", e);
|
||||
handle::Handle::notice_message("import_sub_url::error", e.to_string());
|
||||
handle::Handle::notice(NoticeStatus::ImportSubUrlError, e.to_string());
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -149,11 +150,11 @@ async fn refresh_core_config() {
|
||||
Ok(outcome) => {
|
||||
let message = outcome.to_string();
|
||||
logging!(warn, Type::Config, "Apply config failed: {}", message);
|
||||
handle::Handle::notice_message("config_validate::error", message);
|
||||
handle::Handle::notice(NoticeStatus::ConfigValidateError, message);
|
||||
}
|
||||
Err(err) => {
|
||||
logging!(error, Type::Config, "Apply config error: {err:#}");
|
||||
handle::Handle::notice_message("update_failed", format!("{err}"));
|
||||
handle::Handle::notice(NoticeStatus::UpdateFailed, format!("{err}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user