mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-07 18:42:11 +08:00
refactor: simplfy backend notify message to frontend (#6323)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user