refactor: update AppHandle usage to use Arc<AppHandle> for improved memory management (#4491)

* refactor: update AppHandle usage to use Arc<AppHandle> for improved memory management

* fix: clippy ci

* fix: ensure default_latency_test is safely accessed with non-null assertion
This commit is contained in:
Tunglies
2025-08-23 00:20:58 +08:00
committed by GitHub
parent c416bd5755
commit 0d070fb934
13 changed files with 140 additions and 96 deletions

View File

@@ -42,17 +42,17 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Install Node - name: Install Node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: "22" node-version: "22"
cache: "pnpm" cache: "pnpm"
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Pnpm install and check - name: Pnpm install and check
run: | run: |
pnpm i pnpm i

View File

@@ -4,7 +4,7 @@ use crate::{
utils::{dirs, logging::Type}, utils::{dirs, logging::Type},
wrap_err, wrap_err,
}; };
use tauri::Manager; use tauri::{AppHandle, Manager};
/// 打开应用程序所在目录 /// 打开应用程序所在目录
#[tauri::command] #[tauri::command]
@@ -36,7 +36,7 @@ pub fn open_web_url(url: String) -> CmdResult<()> {
/// 打开/关闭开发者工具 /// 打开/关闭开发者工具
#[tauri::command] #[tauri::command]
pub fn open_devtools(app_handle: tauri::AppHandle) { pub fn open_devtools(app_handle: AppHandle) {
if let Some(window) = app_handle.get_webview_window("main") { if let Some(window) = app_handle.get_webview_window("main") {
if !window.is_devtools_open() { if !window.is_devtools_open() {
window.open_devtools(); window.open_devtools();

View File

@@ -668,10 +668,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult<bool> {
/// 根据profile name修改profiles /// 根据profile name修改profiles
#[tauri::command] #[tauri::command]
pub async fn patch_profiles_config_by_profile_index( pub async fn patch_profiles_config_by_profile_index(profile_index: String) -> CmdResult<bool> {
_app_handle: tauri::AppHandle,
profile_index: String,
) -> CmdResult<bool> {
logging!(info, Type::Cmd, true, "切换配置到: {}", profile_index); logging!(info, Type::Cmd, true, "切换配置到: {}", profile_index);
let profiles = IProfiles { let profiles = IProfiles {
@@ -718,7 +715,7 @@ pub fn patch_profile(index: String, profile: PrfItem) -> CmdResult {
/// 查看配置文件 /// 查看配置文件
#[tauri::command] #[tauri::command]
pub fn view_profile(app_handle: tauri::AppHandle, index: String) -> CmdResult { pub fn view_profile(index: String) -> CmdResult {
let file = { let file = {
wrap_err!(Config::profiles().latest_ref().get_item(&index))? wrap_err!(Config::profiles().latest_ref().get_item(&index))?
.file .file
@@ -731,7 +728,7 @@ pub fn view_profile(app_handle: tauri::AppHandle, index: String) -> CmdResult {
ret_err!("the file not found"); ret_err!("the file not found");
} }
wrap_err!(help::open_file(app_handle, path)) wrap_err!(help::open_file(path))
} }
/// 读取配置文件内容 /// 读取配置文件内容

View File

@@ -255,7 +255,7 @@ impl NotificationSystem {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Handle { pub struct Handle {
pub app_handle: Arc<RwLock<Option<AppHandle>>>, pub app_handle: Arc<RwLock<Option<Arc<AppHandle>>>>,
pub is_exiting: Arc<RwLock<bool>>, pub is_exiting: Arc<RwLock<bool>>,
startup_errors: Arc<RwLock<Vec<ErrorMessage>>>, startup_errors: Arc<RwLock<Vec<ErrorMessage>>>,
startup_completed: Arc<RwLock<bool>>, startup_completed: Arc<RwLock<bool>>,
@@ -282,10 +282,10 @@ impl Handle {
Self::default() Self::default()
} }
pub fn init(&self, app_handle: &AppHandle) { pub fn init(&self, app_handle: Arc<AppHandle>) {
{ {
let mut handle = self.app_handle.write(); let mut handle = self.app_handle.write();
*handle = Some(app_handle.clone()); *handle = Some(Arc::clone(&app_handle));
} }
let mut system_opt = self.notification_system.write(); let mut system_opt = self.notification_system.write();
@@ -294,8 +294,9 @@ impl Handle {
} }
} }
pub fn app_handle(&self) -> Option<AppHandle> { /// 获取 AppHandle
self.app_handle.read().clone() pub fn app_handle(&self) -> Option<Arc<AppHandle>> {
self.app_handle.read().as_ref().map(Arc::clone)
} }
pub fn get_window(&self) -> Option<WebviewWindow> { pub fn get_window(&self) -> Option<WebviewWindow> {

View File

@@ -6,7 +6,7 @@ use crate::{
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{collections::HashMap, fmt, str::FromStr, sync::Arc}; use std::{collections::HashMap, fmt, str::FromStr, sync::Arc};
use tauri::Manager; use tauri::{AppHandle, Manager};
use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, ShortcutState}; use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, ShortcutState};
/// Enum representing all available hotkey functions /// Enum representing all available hotkey functions
@@ -103,7 +103,7 @@ impl Hotkey {
} }
/// Execute the function associated with a hotkey function enum /// Execute the function associated with a hotkey function enum
fn execute_function(function: HotkeyFunction, app_handle: &tauri::AppHandle) { fn execute_function(function: HotkeyFunction, app_handle: Arc<AppHandle>) {
match function { match function {
HotkeyFunction::OpenOrCloseDashboard => { HotkeyFunction::OpenOrCloseDashboard => {
logging!( logging!(
@@ -218,7 +218,7 @@ impl Hotkey {
manager.unregister(hotkey)?; manager.unregister(hotkey)?;
} }
let app_handle_clone = app_handle.clone(); let app_handle_clone = Arc::clone(&app_handle);
let is_quit = matches!(function, HotkeyFunction::Quit); let is_quit = matches!(function, HotkeyFunction::Quit);
let _ = manager.on_shortcut(hotkey, move |app_handle, hotkey_event, event| { let _ = manager.on_shortcut(hotkey, move |app_handle, hotkey_event, event| {
@@ -229,7 +229,7 @@ impl Hotkey {
if let Some(window) = app_handle.get_webview_window("main") { if let Some(window) = app_handle.get_webview_window("main") {
if window.is_focused().unwrap_or(false) { if window.is_focused().unwrap_or(false) {
logging!(debug, Type::Hotkey, "Executing quit function"); logging!(debug, Type::Hotkey, "Executing quit function");
Self::execute_function(function, &app_handle_clone); Self::execute_function(function, Arc::clone(&app_handle_clone));
} }
} }
} else { } else {
@@ -241,14 +241,14 @@ impl Hotkey {
.unwrap_or(true); .unwrap_or(true);
if is_enable_global_hotkey { if is_enable_global_hotkey {
Self::execute_function(function, &app_handle_clone); Self::execute_function(function, Arc::clone(&app_handle_clone));
} else { } else {
use crate::utils::window_manager::WindowManager; use crate::utils::window_manager::WindowManager;
let is_visible = WindowManager::is_main_window_visible(); let is_visible = WindowManager::is_main_window_visible();
let is_focused = WindowManager::is_main_window_focused(); let is_focused = WindowManager::is_main_window_focused();
if is_focused && is_visible { if is_focused && is_visible {
Self::execute_function(function, &app_handle_clone); Self::execute_function(function, Arc::clone(&app_handle_clone));
} }
} }
} }

View File

@@ -15,6 +15,7 @@ use crate::{
use anyhow::Result; use anyhow::Result;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::Arc;
use std::{ use std::{
fs, fs,
sync::atomic::{AtomicBool, Ordering}, sync::atomic::{AtomicBool, Ordering},
@@ -244,7 +245,7 @@ impl Tray {
// 设置更新状态 // 设置更新状态
self.menu_updating.store(true, Ordering::Release); self.menu_updating.store(true, Ordering::Release);
let result = self.update_menu_internal(&app_handle); let result = self.update_menu_internal(app_handle);
{ {
let mut last_update = self.last_menu_update.lock(); let mut last_update = self.last_menu_update.lock();
@@ -255,7 +256,7 @@ impl Tray {
result result
} }
fn update_menu_internal(&self, app_handle: &AppHandle) -> Result<()> { fn update_menu_internal(&self, app_handle: Arc<AppHandle>) -> Result<()> {
let verge = Config::verge().latest_ref().clone(); let verge = Config::verge().latest_ref().clone();
let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false);
@@ -277,7 +278,7 @@ impl Tray {
match app_handle.tray_by_id("main") { match app_handle.tray_by_id("main") {
Some(tray) => { Some(tray) => {
let _ = tray.set_menu(Some(create_tray_menu( let _ = tray.set_menu(Some(create_tray_menu(
app_handle, &app_handle,
Some(mode.as_str()), Some(mode.as_str()),
*system_proxy, *system_proxy,
*tun_mode, *tun_mode,
@@ -451,7 +452,7 @@ impl Tray {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn unsubscribe_traffic(&self) {} pub fn unsubscribe_traffic(&self) {}
pub fn create_tray_from_handle(&self, app_handle: &AppHandle) -> Result<()> { pub fn create_tray_from_handle(&self, app_handle: Arc<AppHandle>) -> Result<()> {
log::info!(target: "app", "正在从AppHandle创建系统托盘"); log::info!(target: "app", "正在从AppHandle创建系统托盘");
// 获取图标 // 获取图标
@@ -477,7 +478,7 @@ impl Tray {
} }
} }
let tray = builder.build(app_handle)?; let tray = builder.build(app_handle.as_ref())?;
tray.on_tray_icon_event(|_, event| { tray.on_tray_icon_event(|_, event| {
let tray_event = { Config::verge().latest_ref().tray_event.clone() }; let tray_event = { Config::verge().latest_ref().tray_event.clone() };

View File

@@ -11,15 +11,7 @@ use anyhow::{bail, Result};
/// Toggle proxy profile /// Toggle proxy profile
pub fn toggle_proxy_profile(profile_index: String) { pub fn toggle_proxy_profile(profile_index: String) {
AsyncHandler::spawn(|| async move { AsyncHandler::spawn(|| async move {
let Some(app_handle) = handle::Handle::global().app_handle() else { match cmd::patch_profiles_config_by_profile_index(profile_index).await {
logging!(
error,
Type::Config,
"Failed to get app handle for profile toggle"
);
return;
};
match cmd::patch_profiles_config_by_profile_index(app_handle, profile_index).await {
Ok(_) => { Ok(_) => {
let _ = tray::Tray::global().update_menu(); let _ = tray::Tray::global().update_menu();
} }

View File

@@ -17,6 +17,7 @@ use crate::{
}; };
use config::Config; use config::Config;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::Arc;
use tauri::AppHandle; use tauri::AppHandle;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use tauri::Manager; use tauri::Manager;
@@ -28,7 +29,7 @@ use utils::logging::Type;
/// A global singleton handle to the application. /// A global singleton handle to the application.
pub struct AppHandleManager { pub struct AppHandleManager {
handle: Mutex<Option<AppHandle>>, handle: Mutex<Option<Arc<AppHandle>>>,
} }
impl AppHandleManager { impl AppHandleManager {
@@ -40,7 +41,7 @@ impl AppHandleManager {
} }
/// Initialize the app handle manager with an app handle. /// Initialize the app handle manager with an app handle.
pub fn init(&self, handle: AppHandle) { pub fn init(&self, handle: Arc<AppHandle>) {
let mut app_handle = self.handle.lock(); let mut app_handle = self.handle.lock();
if app_handle.is_none() { if app_handle.is_none() {
*app_handle = Some(handle); *app_handle = Some(handle);
@@ -54,12 +55,12 @@ impl AppHandleManager {
} }
/// Get the app handle if it has been initialized. /// Get the app handle if it has been initialized.
pub fn get(&self) -> Option<AppHandle> { fn get(&self) -> Option<Arc<AppHandle>> {
self.handle.lock().clone() self.handle.lock().clone()
} }
/// Get the app handle, panics if it hasn't been initialized. /// Get the app handle, panics if it hasn't been initialized.
pub fn get_handle(&self) -> AppHandle { pub fn get_handle(&self) -> Arc<AppHandle> {
if let Some(handle) = self.get() { if let Some(handle) = self.get() {
handle handle
} else { } else {
@@ -246,12 +247,12 @@ mod app_init {
} }
/// Initialize core components asynchronously /// Initialize core components asynchronously
pub fn init_core_async(app_handle: tauri::AppHandle) { pub fn init_core_async(app_handle: Arc<AppHandle>) {
AsyncHandler::spawn(move || async move { AsyncHandler::spawn(move || async move {
logging!(info, Type::Setup, true, "异步执行应用设置..."); logging!(info, Type::Setup, true, "异步执行应用设置...");
match timeout( match timeout(
Duration::from_secs(30), Duration::from_secs(30),
resolve::resolve_setup_async(&app_handle), resolve::resolve_setup_async(app_handle),
) )
.await .await
{ {
@@ -271,12 +272,12 @@ mod app_init {
} }
/// Initialize core components synchronously /// Initialize core components synchronously
pub fn init_core_sync(app_handle: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> { pub fn init_core_sync(app_handle: Arc<AppHandle>) -> Result<(), Box<dyn std::error::Error>> {
logging!(info, Type::Setup, true, "初始化AppHandleManager..."); logging!(info, Type::Setup, true, "初始化AppHandleManager...");
AppHandleManager::global().init(app_handle.clone()); AppHandleManager::global().init(Arc::clone(&app_handle));
logging!(info, Type::Setup, true, "初始化核心句柄..."); logging!(info, Type::Setup, true, "初始化核心句柄...");
core::handle::Handle::global().init(app_handle); core::handle::Handle::global().init(Arc::clone(&app_handle));
logging!(info, Type::Setup, true, "初始化配置..."); logging!(info, Type::Setup, true, "初始化配置...");
utils::init::init_config()?; utils::init::init_config()?;
@@ -482,13 +483,16 @@ pub fn run() {
); );
} }
let app_handle = app.handle().clone();
let app_handle = Arc::new(app_handle);
// Initialize core components asynchronously // Initialize core components asynchronously
app_init::init_core_async(app.handle().clone()); app_init::init_core_async(Arc::clone(&app_handle));
logging!(info, Type::Setup, true, "执行主要设置操作..."); logging!(info, Type::Setup, true, "执行主要设置操作...");
// Initialize core components synchronously // Initialize core components synchronously
if let Err(e) = app_init::init_core_sync(app.handle()) { if let Err(e) = app_init::init_core_sync(Arc::clone(&app_handle)) {
logging!( logging!(
error, error,
Type::Setup, Type::Setup,
@@ -509,9 +513,9 @@ pub fn run() {
use super::*; use super::*;
/// Handle application ready/resumed events /// Handle application ready/resumed events
pub fn handle_ready_resumed(app_handle: &tauri::AppHandle) { pub fn handle_ready_resumed(app_handle: Arc<AppHandle>) {
logging!(info, Type::System, true, "应用就绪或恢复"); logging!(info, Type::System, true, "应用就绪或恢复");
AppHandleManager::global().init(app_handle.clone()); AppHandleManager::global().init(Arc::clone(&app_handle));
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
@@ -524,7 +528,7 @@ pub fn run() {
/// Handle application reopen events (macOS) /// Handle application reopen events (macOS)
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn handle_reopen(app_handle: &tauri::AppHandle, has_visible_windows: bool) { pub fn handle_reopen(app_handle: Arc<AppHandle>, has_visible_windows: bool) {
logging!( logging!(
info, info,
Type::System, Type::System,
@@ -533,7 +537,7 @@ pub fn run() {
has_visible_windows has_visible_windows
); );
AppHandleManager::global().init(app_handle.clone()); AppHandleManager::global().init(Arc::clone(&app_handle));
if !has_visible_windows { if !has_visible_windows {
// 当没有可见窗口时,设置为 regular 模式并显示主窗口 // 当没有可见窗口时,设置为 regular 模式并显示主窗口
@@ -685,45 +689,48 @@ pub fn run() {
std::process::exit(1); std::process::exit(1);
}); });
app.run(|app_handle, e| match e { app.run(|app_handle, e| {
tauri::RunEvent::Ready | tauri::RunEvent::Resumed => { let app_handle = Arc::new(app_handle.clone());
event_handlers::handle_ready_resumed(app_handle); match e {
} tauri::RunEvent::Ready | tauri::RunEvent::Resumed => {
#[cfg(target_os = "macos")] event_handlers::handle_ready_resumed(Arc::clone(&app_handle));
tauri::RunEvent::Reopen {
has_visible_windows,
..
} => {
event_handlers::handle_reopen(app_handle, has_visible_windows);
}
tauri::RunEvent::ExitRequested { api, code, .. } => {
if code.is_none() {
api.prevent_exit();
} }
} #[cfg(target_os = "macos")]
tauri::RunEvent::Exit => { tauri::RunEvent::Reopen {
// Avoid duplicate cleanup has_visible_windows,
if core::handle::Handle::global().is_exiting() { ..
return; } => {
event_handlers::handle_reopen(app_handle, has_visible_windows);
} }
feat::clean(); tauri::RunEvent::ExitRequested { api, code, .. } => {
} if code.is_none() {
tauri::RunEvent::WindowEvent { label, event, .. } => { api.prevent_exit();
if label == "main" {
match event {
tauri::WindowEvent::CloseRequested { .. } => {
event_handlers::handle_window_close(&event);
}
tauri::WindowEvent::Focused(focused) => {
event_handlers::handle_window_focus(focused);
}
tauri::WindowEvent::Destroyed => {
event_handlers::handle_window_destroyed();
}
_ => {}
} }
} }
tauri::RunEvent::Exit => {
// Avoid duplicate cleanup
if core::handle::Handle::global().is_exiting() {
return;
}
feat::clean();
}
tauri::RunEvent::WindowEvent { label, event, .. } => {
if label == "main" {
match event {
tauri::WindowEvent::CloseRequested { .. } => {
event_handlers::handle_window_close(&event);
}
tauri::WindowEvent::Focused(focused) => {
event_handlers::handle_window_focus(focused);
}
tauri::WindowEvent::Destroyed => {
event_handlers::handle_window_destroyed();
}
_ => {}
}
}
}
_ => {}
} }
_ => {}
}); });
} }

View File

@@ -1,22 +1,63 @@
#[cfg(feature = "tokio-trace")]
use std::any::type_name;
use std::future::Future; use std::future::Future;
#[cfg(feature = "tokio-trace")]
use std::panic::Location;
use tauri::{async_runtime, async_runtime::JoinHandle}; use tauri::{async_runtime, async_runtime::JoinHandle};
pub struct AsyncHandler; pub struct AsyncHandler;
impl AsyncHandler { impl AsyncHandler {
#[track_caller]
pub fn spawn<F, Fut>(f: F) -> JoinHandle<()> pub fn spawn<F, Fut>(f: F) -> JoinHandle<()>
where where
F: FnOnce() -> Fut + Send + 'static, F: FnOnce() -> Fut + Send + 'static,
Fut: Future<Output = ()> + Send + 'static, Fut: Future<Output = ()> + Send + 'static,
{ {
#[cfg(feature = "tokio-trace")]
Self::log_task_info(&f);
async_runtime::spawn(f()) async_runtime::spawn(f())
} }
#[track_caller]
pub fn spawn_blocking<T, F>(f: F) -> JoinHandle<T> pub fn spawn_blocking<T, F>(f: F) -> JoinHandle<T>
where where
F: FnOnce() -> T + Send + 'static, F: FnOnce() -> T + Send + 'static,
T: Send + 'static, T: Send + 'static,
{ {
#[cfg(feature = "tokio-trace")]
Self::log_task_info(&f);
async_runtime::spawn_blocking(f) async_runtime::spawn_blocking(f)
} }
#[cfg(feature = "tokio-trace")]
#[track_caller]
fn log_task_info<F>(f: &F)
where
F: ?Sized,
{
const TRACE_MINI_SIZE: usize = 0;
let size = std::mem::size_of_val(f);
if size <= TRACE_MINI_SIZE {
return;
}
let location = Location::caller();
let type_str = type_name::<F>();
let size_str = format!("{} bytes", size);
let loc_str = format!(
"{}:{}:{}",
location.file(),
location.line(),
location.column()
);
println!("┌────────────────────┬─────────────────────────────────────────────────────────────────────────────┐");
println!("{:<18}{:<80}", "Field", "Value");
println!("├────────────────────┼─────────────────────────────────────────────────────────────────────────────┤");
println!("{:<18}{:<80}", "Type of task", type_str);
println!("{:<18}{:<80}", "Size of task", size_str);
println!("{:<18}{:<80}", "Called from", loc_str);
println!("└────────────────────┴─────────────────────────────────────────────────────────────────────────────┘");
}
} }

View File

@@ -120,7 +120,7 @@ pub fn get_last_part_and_decode(url: &str) -> Option<String> {
} }
/// open file /// open file
pub fn open_file(_: tauri::AppHandle, path: PathBuf) -> Result<()> { pub fn open_file(path: PathBuf) -> Result<()> {
open::that_detached(path.as_os_str())?; open::that_detached(path.as_os_str())?;
Ok(()) Ok(())
} }

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use tauri::AppHandle; use tauri::AppHandle;
use tauri_plugin_notification::NotificationExt; use tauri_plugin_notification::NotificationExt;
@@ -14,7 +16,7 @@ pub enum NotificationEvent<'a> {
AppHidden, AppHidden,
} }
fn notify(app: &AppHandle, title: &str, body: &str) { fn notify(app: Arc<AppHandle>, title: &str, body: &str) {
app.notification() app.notification()
.builder() .builder()
.title(title) .title(title)
@@ -23,7 +25,7 @@ fn notify(app: &AppHandle, title: &str, body: &str) {
.ok(); .ok();
} }
pub fn notify_event(app: &AppHandle, event: NotificationEvent) { pub fn notify_event(app: Arc<AppHandle>, event: NotificationEvent) {
use crate::utils::i18n::t; use crate::utils::i18n::t;
match event { match event {
NotificationEvent::DashboardToggled => { NotificationEvent::DashboardToggled => {

View File

@@ -14,7 +14,10 @@ use once_cell::sync::OnceCell;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use scopeguard; use scopeguard;
use std::time::{Duration, Instant}; use std::{
sync::Arc,
time::{Duration, Instant},
};
use tauri::{AppHandle, Manager}; use tauri::{AppHandle, Manager};
use tauri::Url; use tauri::Url;
@@ -106,7 +109,7 @@ pub fn reset_ui_ready() {
} }
/// 异步方式处理启动后的额外任务 /// 异步方式处理启动后的额外任务
pub async fn resolve_setup_async(app_handle: &AppHandle) { pub async fn resolve_setup_async(app_handle: Arc<AppHandle>) {
let start_time = std::time::Instant::now(); let start_time = std::time::Instant::now();
logging!( logging!(
info, info,
@@ -162,7 +165,7 @@ pub async fn resolve_setup_async(app_handle: &AppHandle) {
if let Some(app_handle) = handle::Handle::global().app_handle() { if let Some(app_handle) = handle::Handle::global().app_handle() {
logging!(info, Type::Tray, true, "创建系统托盘..."); logging!(info, Type::Tray, true, "创建系统托盘...");
let result = tray::Tray::global().create_tray_from_handle(&app_handle); let result = tray::Tray::global().create_tray_from_handle(app_handle);
if result.is_ok() { if result.is_ok() {
logging!(info, Type::Tray, true, "系统托盘创建成功"); logging!(info, Type::Tray, true, "系统托盘创建成功");
} else if let Err(e) = result { } else if let Err(e) = result {
@@ -329,7 +332,7 @@ pub fn create_window(is_show: bool) -> bool {
}; };
match tauri::WebviewWindowBuilder::new( match tauri::WebviewWindowBuilder::new(
&app_handle, &*app_handle,
"main", /* the unique window label */ "main", /* the unique window label */
tauri::WebviewUrl::App("index.html".into()), tauri::WebviewUrl::App("index.html".into()),
) )

View File

@@ -48,7 +48,7 @@ export const ProxyHead = (props: Props) => {
useEffect(() => { useEffect(() => {
delayManager.setUrl( delayManager.setUrl(
groupName, groupName,
testUrl || url || verge?.default_latency_test, testUrl || url || verge?.default_latency_test!,
); );
}, [groupName, testUrl, verge?.default_latency_test]); }, [groupName, testUrl, verge?.default_latency_test]);