mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-13 05:20:28 +08:00
refactor: simplfy backend notify message to frontend (#6323)
This commit is contained in:
parent
e5dd127bcc
commit
5f573ca2d6
@ -23,7 +23,6 @@ pub mod timing {
|
||||
use super::Duration;
|
||||
|
||||
pub const CONFIG_UPDATE_DEBOUNCE: Duration = Duration::from_millis(300);
|
||||
pub const EVENT_EMIT_DELAY: Duration = Duration::from_millis(20);
|
||||
pub const STARTUP_ERROR_DELAY: Duration = Duration::from_secs(2);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
use crate::{APP_HANDLE, singleton, utils::window_manager::WindowManager};
|
||||
use parking_lot::RwLock;
|
||||
use crate::{APP_HANDLE, singleton};
|
||||
use smartstring::alias::String;
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use tauri::AppHandle;
|
||||
use tauri_plugin_mihomo::{Mihomo, MihomoExt as _};
|
||||
use tokio::sync::RwLockReadGuard;
|
||||
@ -14,14 +10,12 @@ use super::notification::{FrontendEvent, NotificationSystem};
|
||||
#[derive(Debug)]
|
||||
pub struct Handle {
|
||||
is_exiting: AtomicBool,
|
||||
pub(crate) notification_system: Arc<RwLock<Option<NotificationSystem>>>,
|
||||
}
|
||||
|
||||
impl Default for Handle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
is_exiting: AtomicBool::new(false),
|
||||
notification_system: Arc::new(RwLock::new(Some(NotificationSystem::new()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,19 +27,6 @@ impl Handle {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
if self.is_exiting() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut system_opt = self.notification_system.write();
|
||||
if let Some(system) = system_opt.as_mut()
|
||||
&& !system.is_running()
|
||||
{
|
||||
system.start();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn app_handle() -> &'static AppHandle {
|
||||
#[allow(clippy::expect_used)]
|
||||
APP_HANDLE.get().expect("App handle not initialized")
|
||||
@ -56,27 +37,11 @@ impl Handle {
|
||||
}
|
||||
|
||||
pub fn refresh_clash() {
|
||||
let handle = Self::global();
|
||||
if handle.is_exiting() {
|
||||
return;
|
||||
}
|
||||
|
||||
let system_opt = handle.notification_system.read();
|
||||
if let Some(system) = system_opt.as_ref() {
|
||||
system.send_event(FrontendEvent::RefreshClash);
|
||||
}
|
||||
Self::send_event(FrontendEvent::RefreshClash);
|
||||
}
|
||||
|
||||
pub fn refresh_verge() {
|
||||
let handle = Self::global();
|
||||
if handle.is_exiting() {
|
||||
return;
|
||||
}
|
||||
|
||||
let system_opt = handle.notification_system.read();
|
||||
if let Some(system) = system_opt.as_ref() {
|
||||
system.send_event(FrontendEvent::RefreshVerge);
|
||||
}
|
||||
Self::send_event(FrontendEvent::RefreshVerge);
|
||||
}
|
||||
|
||||
pub fn notify_profile_changed(profile_id: String) {
|
||||
@ -99,17 +64,6 @@ impl Handle {
|
||||
|
||||
// TODO 利用 &str 等缩短 Clone
|
||||
pub fn notice_message<S: Into<String>, M: Into<String>>(status: S, msg: M) {
|
||||
let handle = Self::global();
|
||||
|
||||
if handle.is_exiting() {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only send notice when main window exists
|
||||
if WindowManager::get_main_window().is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let status_str = status.into();
|
||||
let msg_str = msg.into();
|
||||
|
||||
@ -119,29 +73,21 @@ impl Handle {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_is_exiting(&self) {
|
||||
self.is_exiting.store(true, Ordering::Release);
|
||||
}
|
||||
|
||||
pub fn is_exiting(&self) -> bool {
|
||||
self.is_exiting.load(Ordering::Acquire)
|
||||
}
|
||||
|
||||
fn send_event(event: FrontendEvent) {
|
||||
let handle = Self::global();
|
||||
if handle.is_exiting() {
|
||||
return;
|
||||
}
|
||||
|
||||
let system_opt = handle.notification_system.read();
|
||||
if let Some(system) = system_opt.as_ref() {
|
||||
system.send_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_is_exiting(&self) {
|
||||
self.is_exiting.store(true, Ordering::Release);
|
||||
|
||||
let mut system_opt = self.notification_system.write();
|
||||
if let Some(system) = system_opt.as_mut() {
|
||||
system.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_exiting(&self) -> bool {
|
||||
self.is_exiting.load(Ordering::Acquire)
|
||||
NotificationSystem::send_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use super::handle::Handle;
|
||||
use crate::{constants::timing, utils::window_manager::WindowManager};
|
||||
use crate::utils::window_manager::WindowManager;
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use serde_json::json;
|
||||
use smartstring::alias::String;
|
||||
use std::{sync::mpsc, thread};
|
||||
|
||||
use tauri::{Emitter as _, WebviewWindow};
|
||||
|
||||
// TODO 重构或优化,避免 Clone 过多
|
||||
@ -18,83 +18,11 @@ pub enum FrontendEvent {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NotificationSystem {
|
||||
sender: Option<mpsc::Sender<FrontendEvent>>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
worker_handle: Option<thread::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl Default for NotificationSystem {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
pub struct NotificationSystem {}
|
||||
|
||||
impl NotificationSystem {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
sender: None,
|
||||
worker_handle: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn is_running(&self) -> bool {
|
||||
self.sender.is_some() && self.worker_handle.is_some()
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
if self.is_running() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
self.sender = Some(tx);
|
||||
|
||||
//? Do we have to create a new thread for this?
|
||||
let result = thread::Builder::new()
|
||||
.name("frontend-notifier".into())
|
||||
.spawn(move || Self::worker_loop(rx));
|
||||
|
||||
match result {
|
||||
Ok(handle) => self.worker_handle = Some(handle),
|
||||
Err(e) => logging!(error, Type::System, "Failed to start notification worker: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn worker_loop(rx: mpsc::Receiver<FrontendEvent>) {
|
||||
let handle = Handle::global();
|
||||
loop {
|
||||
if handle.is_exiting() {
|
||||
break;
|
||||
}
|
||||
match rx.recv() {
|
||||
Ok(event) => Self::process_event(handle, event),
|
||||
Err(e) => {
|
||||
logging!(error, Type::System, "Notification System will exit, recv error: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_event(handle: &super::handle::Handle, event: FrontendEvent) {
|
||||
let binding = handle.notification_system.read();
|
||||
let system = match binding.as_ref() {
|
||||
Some(s) => s,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if let Some(window) = WindowManager::get_main_window() {
|
||||
system.emit_to_window(&window, event);
|
||||
drop(binding);
|
||||
thread::sleep(timing::EVENT_EMIT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_to_window(&self, window: &WebviewWindow, event: FrontendEvent) {
|
||||
let (event_name, payload) = self.serialize_event(event);
|
||||
|
||||
let Ok(payload) = payload else {
|
||||
fn emit_to_window(window: &WebviewWindow, event: FrontendEvent) {
|
||||
let (event_name, Ok(payload)) = Self::serialize_event(event) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@ -103,9 +31,7 @@ impl NotificationSystem {
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_event(&self, event: FrontendEvent) -> (&'static str, Result<serde_json::Value, serde_json::Error>) {
|
||||
use serde_json::json;
|
||||
|
||||
fn serialize_event(event: FrontendEvent) -> (&'static str, Result<serde_json::Value, serde_json::Error>) {
|
||||
match event {
|
||||
FrontendEvent::RefreshClash => ("verge://refresh-clash-config", Ok(json!("yes"))),
|
||||
FrontendEvent::RefreshVerge => ("verge://refresh-verge-config", Ok(json!("yes"))),
|
||||
@ -119,25 +45,9 @@ impl NotificationSystem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_event(&self, event: FrontendEvent) -> bool {
|
||||
if !self.is_running() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(sender) = &self.sender {
|
||||
sender.send(event).is_ok()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown(&mut self) {
|
||||
if let Some(sender) = self.sender.take() {
|
||||
drop(sender);
|
||||
}
|
||||
|
||||
if let Some(handle) = self.worker_handle.take() {
|
||||
let _ = handle.join();
|
||||
pub(crate) fn send_event(event: FrontendEvent) {
|
||||
if let Some(window) = WindowManager::get_main_window() {
|
||||
Self::emit_to_window(&window, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +250,6 @@ pub fn run() {
|
||||
logging!(error, Type::Setup, "Failed to setup window state: {}", e);
|
||||
}
|
||||
|
||||
resolve::resolve_setup_handle();
|
||||
resolve::resolve_setup_async();
|
||||
resolve::resolve_setup_sync();
|
||||
resolve::init_signal();
|
||||
@ -282,7 +281,6 @@ pub fn run() {
|
||||
}
|
||||
|
||||
logging!(info, Type::System, "应用就绪");
|
||||
handle::Handle::global().init();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Some(window) = _app_handle.get_webview_window("main") {
|
||||
@ -292,8 +290,6 @@ pub fn run() {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn handle_reopen(has_visible_windows: bool) {
|
||||
handle::Handle::global().init();
|
||||
|
||||
if lightweight::is_in_lightweight_mode() {
|
||||
lightweight::exit_lightweight_mode().await;
|
||||
return;
|
||||
|
||||
@ -5,7 +5,7 @@ use anyhow::Result;
|
||||
use crate::{
|
||||
config::Config,
|
||||
core::{
|
||||
CoreManager, Timer, handle,
|
||||
CoreManager, Timer,
|
||||
hotkey::Hotkey,
|
||||
logger::Logger,
|
||||
service::{SERVICE_MANAGER, ServiceManager, is_service_ipc_path_exists},
|
||||
@ -39,10 +39,6 @@ pub fn init_work_dir_and_logger() -> anyhow::Result<()> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_setup_handle() {
|
||||
init_handle();
|
||||
}
|
||||
|
||||
pub fn resolve_setup_sync() {
|
||||
AsyncHandler::spawn(|| async {
|
||||
AsyncHandler::spawn_blocking(init_scheme);
|
||||
@ -95,10 +91,6 @@ pub async fn resolve_reset_async() -> Result<(), anyhow::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init_handle() {
|
||||
handle::Handle::global().init();
|
||||
}
|
||||
|
||||
pub(super) fn init_scheme() {
|
||||
logging_error!(Type::Setup, init::init_scheme());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user