refactor: replace AppHandleManager with handle::Handle for macOS activation policy management

This commit is contained in:
Tunglies
2025-08-28 17:27:54 +08:00
parent 53688f332f
commit a9951e4eca
6 changed files with 72 additions and 143 deletions

View File

@@ -294,6 +294,10 @@ impl Handle {
} }
} }
pub fn is_initialized(&self) -> bool {
self.app_handle().is_some()
}
/// 获取 AppHandle /// 获取 AppHandle
pub fn app_handle(&self) -> Option<AppHandle> { pub fn app_handle(&self) -> Option<AppHandle> {
self.app_handle.read().clone() self.app_handle.read().clone()
@@ -522,3 +526,54 @@ impl Handle {
*self.is_exiting.read() *self.is_exiting.read()
} }
} }
#[cfg(target_os = "macos")]
impl Handle {
pub fn set_activation_policy(&self, policy: tauri::ActivationPolicy) -> Result<(), String> {
let app_handle = self.app_handle();
if let Some(app_handle) = app_handle.as_ref() {
app_handle
.set_activation_policy(policy)
.map_err(|e| e.to_string())
} else {
Err("AppHandle not initialized".to_string())
}
}
pub fn set_activation_policy_regular(&self) {
if let Err(e) = self.set_activation_policy(tauri::ActivationPolicy::Regular) {
logging!(
warn,
Type::Setup,
true,
"Failed to set regular activation policy: {}",
e
);
}
}
pub fn set_activation_policy_accessory(&self) {
if let Err(e) = self.set_activation_policy(tauri::ActivationPolicy::Accessory) {
logging!(
warn,
Type::Setup,
true,
"Failed to set accessory activation policy: {}",
e
);
}
}
#[allow(dead_code)]
pub fn set_activation_policy_prohibited(&self) {
if let Err(e) = self.set_activation_policy(tauri::ActivationPolicy::Prohibited) {
logging!(
warn,
Type::Setup,
true,
"Failed to set prohibited activation policy: {}",
e
);
}
}
}

View File

@@ -1,5 +1,3 @@
#[cfg(target_os = "macos")]
use crate::AppHandleManager;
use crate::{ use crate::{
config::Config, config::Config,
core::{handle, sysopt, CoreManager}, core::{handle, sysopt, CoreManager},
@@ -259,5 +257,5 @@ pub async fn hide() {
let _ = window.hide(); let _ = window.hide();
} }
} }
AppHandleManager::global().set_activation_policy_accessory(); handle::Handle::global().set_activation_policy_accessory();
} }

View File

@@ -26,120 +26,10 @@ use tauri_plugin_deep_link::DeepLinkExt;
use tokio::time::{timeout, Duration}; use tokio::time::{timeout, Duration};
use utils::logging::Type; use utils::logging::Type;
/// A global singleton handle to the application.
pub struct AppHandleManager {
handle: Mutex<Option<AppHandle>>,
}
impl AppHandleManager {
/// Create a new AppHandleManager instance
fn new() -> Self {
Self {
handle: Mutex::new(None),
}
}
/// Initialize the app handle manager with an app handle.
pub fn init(&self, handle: AppHandle) {
let mut app_handle = self.handle.lock();
if app_handle.is_none() {
*app_handle = Some(handle);
logging!(
info,
Type::Setup,
true,
"AppHandleManager initialized with handle"
);
}
}
/// Get the app handle if it has been initialized.
fn get(&self) -> Option<AppHandle> {
self.handle.lock().clone()
}
/// Get the app handle, panics if it hasn't been initialized.
pub fn get_handle(&self) -> AppHandle {
if let Some(handle) = self.get() {
handle
} else {
logging!(
error,
Type::Setup,
"AppHandle not initialized - ensure init() was called first"
);
std::process::exit(1)
}
}
/// Check if the app handle has been initialized.
pub fn is_initialized(&self) -> bool {
self.handle.lock().is_some()
}
#[cfg(target_os = "macos")]
pub fn set_activation_policy(&self, policy: tauri::ActivationPolicy) -> Result<(), String> {
let app_handle = self.handle.lock();
if let Some(app_handle) = app_handle.as_ref() {
app_handle
.set_activation_policy(policy)
.map_err(|e| e.to_string())
} else {
Err("AppHandle not initialized".to_string())
}
}
pub fn set_activation_policy_regular(&self) {
#[cfg(target_os = "macos")]
{
if let Err(e) = self.set_activation_policy(tauri::ActivationPolicy::Regular) {
logging!(
warn,
Type::Setup,
true,
"Failed to set regular activation policy: {}",
e
);
}
}
}
pub fn set_activation_policy_accessory(&self) {
#[cfg(target_os = "macos")]
{
if let Err(e) = self.set_activation_policy(tauri::ActivationPolicy::Accessory) {
logging!(
warn,
Type::Setup,
true,
"Failed to set accessory activation policy: {}",
e
);
}
}
}
pub fn set_activation_policy_prohibited(&self) {
#[cfg(target_os = "macos")]
{
if let Err(e) = self.set_activation_policy(tauri::ActivationPolicy::Prohibited) {
logging!(
warn,
Type::Setup,
true,
"Failed to set prohibited activation policy: {}",
e
);
}
}
}
}
// Use unified singleton macro
singleton_with_logging!(AppHandleManager, INSTANCE, "AppHandleManager");
/// Application initialization helper functions /// Application initialization helper functions
mod app_init { mod app_init {
use crate::core::handle;
use super::*; use super::*;
/// Initialize singleton monitoring for other instances /// Initialize singleton monitoring for other instances
@@ -150,8 +40,8 @@ mod app_init {
Ok(result) => { Ok(result) => {
if result.is_err() { if result.is_err() {
logging!(info, Type::Setup, true, "检测到已有应用实例运行"); logging!(info, Type::Setup, true, "检测到已有应用实例运行");
if let Some(app_handle) = AppHandleManager::global().get() { if handle::Handle::global().is_initialized() {
app_handle.exit(0); handle::Handle::global().app_handle().unwrap().exit(0);
} else { } else {
std::process::exit(0); std::process::exit(0);
} }
@@ -271,9 +161,6 @@ mod app_init {
/// Initialize core components synchronously /// Initialize core components synchronously
pub async fn init_core_sync(app_handle: &AppHandle) -> Result<(), Box<dyn std::error::Error>> { pub async fn init_core_sync(app_handle: &AppHandle) -> Result<(), Box<dyn std::error::Error>> {
logging!(info, Type::Setup, true, "初始化AppHandleManager...");
AppHandleManager::global().init(app_handle.clone());
logging!(info, Type::Setup, true, "初始化核心句柄..."); logging!(info, Type::Setup, true, "初始化核心句柄...");
core::handle::Handle::global().init(app_handle.clone()); core::handle::Handle::global().init(app_handle.clone());
@@ -509,12 +396,14 @@ pub fn run() {
/// Event handling helper functions /// Event handling helper functions
mod event_handlers { mod event_handlers {
use crate::core::handle;
use super::*; use super::*;
/// Handle application ready/resumed events /// Handle application ready/resumed events
pub fn handle_ready_resumed(app_handle: &AppHandle) { pub fn handle_ready_resumed(app_handle: &AppHandle) {
logging!(info, Type::System, true, "应用就绪或恢复"); logging!(info, Type::System, true, "应用就绪或恢复");
AppHandleManager::global().init(app_handle.clone()); handle::Handle::global().init(app_handle.clone());
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
@@ -536,11 +425,11 @@ pub fn run() {
has_visible_windows has_visible_windows
); );
AppHandleManager::global().init(app_handle.clone()); handle::Handle::global().init(app_handle.clone());
if !has_visible_windows { if !has_visible_windows {
// 当没有可见窗口时,设置为 regular 模式并显示主窗口 // 当没有可见窗口时,设置为 regular 模式并显示主窗口
AppHandleManager::global().set_activation_policy_regular(); handle::Handle::global().set_activation_policy_regular();
logging!(info, Type::System, true, "没有可见窗口,尝试显示主窗口"); logging!(info, Type::System, true, "没有可见窗口,尝试显示主窗口");
@@ -560,7 +449,7 @@ pub fn run() {
/// Handle window close requests /// Handle window close requests
pub fn handle_window_close(api: &tauri::WindowEvent) { pub fn handle_window_close(api: &tauri::WindowEvent) {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
AppHandleManager::global().set_activation_policy_accessory(); handle::Handle::global().set_activation_policy_accessory();
if core::handle::Handle::global().is_exiting() { if core::handle::Handle::global().is_exiting() {
return; return;

View File

@@ -9,8 +9,6 @@ use crate::{
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use crate::logging_error; use crate::logging_error;
#[cfg(target_os = "macos")]
use crate::AppHandleManager;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use delay_timer::prelude::TaskBuilder; use delay_timer::prelude::TaskBuilder;
@@ -173,7 +171,7 @@ pub async fn entry_lightweight_mode() {
let _ = webview.destroy(); let _ = webview.destroy();
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
AppHandleManager::global().set_activation_policy_accessory(); handle::Handle::global().set_activation_policy_accessory();
} }
set_lightweight_mode(true).await; set_lightweight_mode(true).await;
let _ = cancel_light_weight_timer(); let _ = cancel_light_weight_timer();
@@ -213,7 +211,7 @@ pub async fn exit_lightweight_mode() {
// macOS激活策略 // macOS激活策略
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
AppHandleManager::global().set_activation_policy_regular(); handle::Handle::global().set_activation_policy_regular();
// 重置UI就绪状态 // 重置UI就绪状态
crate::utils::resolve::reset_ui_ready(); crate::utils::resolve::reset_ui_ready();

View File

@@ -1,5 +1,3 @@
#[cfg(target_os = "macos")]
use crate::AppHandleManager;
use crate::{ use crate::{
config::{Config, PrfItem}, config::{Config, PrfItem},
core::*, core::*,
@@ -185,9 +183,7 @@ pub async fn resolve_setup_async(app_handle: &AppHandle) {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
if is_silent_start { if is_silent_start {
use crate::AppHandleManager; handle::Handle::global().set_activation_policy_accessory();
AppHandleManager::global().set_activation_policy_accessory();
} }
} }
create_window(!is_silent_start).await; create_window(!is_silent_start).await;
@@ -273,9 +269,7 @@ pub async fn create_window(is_show: bool) -> bool {
let _ = window.set_focus(); let _ = window.set_focus();
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ handle::Handle::global().set_activation_policy_regular();
AppHandleManager::global().set_activation_policy_regular();
}
} }
return true; return true;
} }
@@ -432,9 +426,7 @@ pub async fn create_window(is_show: bool) -> bool {
let _ = window_clone.set_focus(); let _ = window_clone.set_focus();
logging!(info, Type::Window, true, "窗口已立即显示"); logging!(info, Type::Window, true, "窗口已立即显示");
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ handle::Handle::global().set_activation_policy_regular();
AppHandleManager::global().set_activation_policy_regular();
}
let timeout_seconds = if crate::module::lightweight::is_in_lightweight_mode() { let timeout_seconds = if crate::module::lightweight::is_in_lightweight_mode() {
3 3

View File

@@ -1,9 +1,6 @@
use crate::{core::handle, logging, utils::logging::Type}; use crate::{core::handle, logging, utils::logging::Type};
use tauri::{Manager, WebviewWindow, Wry}; use tauri::{Manager, WebviewWindow, Wry};
#[cfg(target_os = "macos")]
use crate::AppHandleManager;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use parking_lot::Mutex; use parking_lot::Mutex;
use scopeguard; use scopeguard;
@@ -283,7 +280,7 @@ impl WindowManager {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
logging!(info, Type::Window, true, "应用 macOS 特定的激活策略"); logging!(info, Type::Window, true, "应用 macOS 特定的激活策略");
AppHandleManager::global().set_activation_policy_regular(); handle::Handle::global().set_activation_policy_regular();
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]