mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-18 16:30:32 +08:00
refactor: reduce webview lock contention (#6271)
* refactor: replace handle::Handle::get_window() with WindowManager::get_main_window() in multiple files * refactor: enhance WindowManager to return window state alongside the main window instance * refactor: update useProfiles and ProfilePage to support profile overrides and improve patchProfilesConfig return type * refactor: enhance handle_success to check main window existence before notifying profile changes * refactor: simplify get_main_window_with_state by using pattern matching and improve window state handling * refactor: fix window activation by removing unnecessary reference in activate_existing_main_window * refactor: remove redundant macOS conditional for window_manager import
This commit is contained in:
parent
6c6e0812b8
commit
c30eaa3678
@ -1,5 +1,6 @@
|
|||||||
use super::CmdResult;
|
use super::CmdResult;
|
||||||
use super::StringifyErr as _;
|
use super::StringifyErr as _;
|
||||||
|
use crate::utils::window_manager::WindowManager;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{
|
config::{
|
||||||
Config, IProfiles, PrfItem, PrfOption,
|
Config, IProfiles, PrfItem, PrfOption,
|
||||||
@ -310,7 +311,9 @@ async fn handle_success(current_value: Option<&String>) -> CmdResult<bool> {
|
|||||||
logging!(warn, Type::Cmd, "Warning: 异步保存配置文件失败: {e}");
|
logging!(warn, Type::Cmd, "Warning: 异步保存配置文件失败: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(current) = current_value {
|
if let Some(current) = current_value
|
||||||
|
&& WindowManager::get_main_window().is_some()
|
||||||
|
{
|
||||||
logging!(info, Type::Cmd, "向前端发送配置变更事件: {}", current);
|
logging!(info, Type::Cmd, "向前端发送配置变更事件: {}", current);
|
||||||
handle::Handle::notify_profile_changed(current.to_owned());
|
handle::Handle::notify_profile_changed(current.to_owned());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use std::sync::{
|
|||||||
Arc,
|
Arc,
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
use tauri::{AppHandle, Manager as _, WebviewWindow};
|
use tauri::AppHandle;
|
||||||
use tauri_plugin_mihomo::{Mihomo, MihomoExt as _};
|
use tauri_plugin_mihomo::{Mihomo, MihomoExt as _};
|
||||||
use tokio::sync::RwLockReadGuard;
|
use tokio::sync::RwLockReadGuard;
|
||||||
|
|
||||||
@ -55,10 +55,6 @@ impl Handle {
|
|||||||
Self::app_handle().mihomo().read().await
|
Self::app_handle().mihomo().read().await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_window() -> Option<WebviewWindow> {
|
|
||||||
Self::app_handle().get_webview_window("main")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn refresh_clash() {
|
pub fn refresh_clash() {
|
||||||
let handle = Self::global();
|
let handle = Self::global();
|
||||||
if handle.is_exiting() {
|
if handle.is_exiting() {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::process::AsyncHandler;
|
use crate::process::AsyncHandler;
|
||||||
use crate::singleton;
|
use crate::singleton;
|
||||||
use crate::utils::notification::{NotificationEvent, notify_event};
|
use crate::utils::notification::{NotificationEvent, notify_event};
|
||||||
|
use crate::utils::window_manager::WindowManager;
|
||||||
use crate::{config::Config, core::handle, feat, module::lightweight::entry_lightweight_mode};
|
use crate::{config::Config, core::handle, feat, module::lightweight::entry_lightweight_mode};
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
@ -243,7 +244,7 @@ impl Hotkey {
|
|||||||
logging!(debug, Type::Hotkey, "Hotkey pressed: {:?}", hotkey_event);
|
logging!(debug, Type::Hotkey, "Hotkey pressed: {:?}", hotkey_event);
|
||||||
let hotkey = hotkey_event.key;
|
let hotkey = hotkey_event.key;
|
||||||
if hotkey == Code::KeyQ && is_quit {
|
if hotkey == Code::KeyQ && is_quit {
|
||||||
if let Some(window) = handle::Handle::get_window()
|
if let Some(window) = WindowManager::get_main_window()
|
||||||
&& window.is_focused().unwrap_or(false)
|
&& window.is_focused().unwrap_or(false)
|
||||||
{
|
{
|
||||||
logging!(debug, Type::Hotkey, "Executing quit function");
|
logging!(debug, Type::Hotkey, "Executing quit function");
|
||||||
@ -260,8 +261,9 @@ impl Hotkey {
|
|||||||
Self::execute_function(function);
|
Self::execute_function(function);
|
||||||
} else {
|
} else {
|
||||||
use crate::utils::window_manager::WindowManager;
|
use crate::utils::window_manager::WindowManager;
|
||||||
let is_visible = WindowManager::is_main_window_visible();
|
let window = WindowManager::get_main_window();
|
||||||
let is_focused = WindowManager::is_main_window_focused();
|
let is_visible = WindowManager::is_main_window_visible(window.as_ref());
|
||||||
|
let is_focused = WindowManager::is_main_window_focused(window.as_ref());
|
||||||
|
|
||||||
if is_focused && is_visible {
|
if is_focused && is_visible {
|
||||||
Self::execute_function(function);
|
Self::execute_function(function);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use super::handle::Handle;
|
use super::handle::Handle;
|
||||||
use crate::constants::timing;
|
use crate::{constants::timing, utils::window_manager::WindowManager};
|
||||||
use clash_verge_logging::{Type, logging};
|
use clash_verge_logging::{Type, logging};
|
||||||
use smartstring::alias::String;
|
use smartstring::alias::String;
|
||||||
use std::{sync::mpsc, thread};
|
use std::{sync::mpsc, thread};
|
||||||
@ -84,7 +84,7 @@ impl NotificationSystem {
|
|||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(window) = super::handle::Handle::get_window() {
|
if let Some(window) = WindowManager::get_main_window() {
|
||||||
system.emit_to_window(&window, event);
|
system.emit_to_window(&window, event);
|
||||||
drop(binding);
|
drop(binding);
|
||||||
thread::sleep(timing::EVENT_EMIT_DELAY);
|
thread::sleep(timing::EVENT_EMIT_DELAY);
|
||||||
|
|||||||
@ -178,7 +178,7 @@ pub async fn hide() {
|
|||||||
add_light_weight_timer().await;
|
add_light_weight_timer().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(window) = handle::Handle::get_window()
|
if let Some(window) = WindowManager::get_main_window()
|
||||||
&& window.is_visible().unwrap_or(false)
|
&& window.is_visible().unwrap_or(false)
|
||||||
{
|
{
|
||||||
let _ = window.hide();
|
let _ = window.hide();
|
||||||
|
|||||||
@ -264,7 +264,6 @@ pub fn run() {
|
|||||||
mod event_handlers {
|
mod event_handlers {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use crate::module::lightweight;
|
use crate::module::lightweight;
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use crate::utils::window_manager::WindowManager;
|
use crate::utils::window_manager::WindowManager;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
@ -316,7 +315,7 @@ pub fn run() {
|
|||||||
|
|
||||||
if let tauri::WindowEvent::CloseRequested { api, .. } = api {
|
if let tauri::WindowEvent::CloseRequested { api, .. } = api {
|
||||||
api.prevent_close();
|
api.prevent_close();
|
||||||
if let Some(window) = core::handle::Handle::get_window() {
|
if let Some(window) = WindowManager::get_main_window() {
|
||||||
let _ = window.hide();
|
let _ = window.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
core::{handle, timer::Timer, tray::Tray},
|
core::{timer::Timer, tray::Tray},
|
||||||
process::AsyncHandler,
|
process::AsyncHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ pub async fn add_light_weight_timer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_window_close_listener() {
|
fn setup_window_close_listener() {
|
||||||
if let Some(window) = handle::Handle::get_window() {
|
if let Some(window) = WindowManager::get_main_window() {
|
||||||
let handler_id = window.listen("tauri://close-requested", move |_event| {
|
let handler_id = window.listen("tauri://close-requested", move |_event| {
|
||||||
std::mem::drop(AsyncHandler::spawn(|| async {
|
std::mem::drop(AsyncHandler::spawn(|| async {
|
||||||
if let Err(e) = setup_light_weight_timer().await {
|
if let Err(e) = setup_light_weight_timer().await {
|
||||||
@ -161,7 +161,7 @@ fn setup_window_close_listener() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cancel_window_close_listener() {
|
fn cancel_window_close_listener() {
|
||||||
if let Some(window) = handle::Handle::get_window() {
|
if let Some(window) = WindowManager::get_main_window() {
|
||||||
let id = WINDOW_CLOSE_HANDLER_ID.swap(0, Ordering::AcqRel);
|
let id = WINDOW_CLOSE_HANDLER_ID.swap(0, Ordering::AcqRel);
|
||||||
if id != 0 {
|
if id != 0 {
|
||||||
window.unlisten(id);
|
window.unlisten(id);
|
||||||
@ -171,7 +171,7 @@ fn cancel_window_close_listener() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_webview_focus_listener() {
|
fn setup_webview_focus_listener() {
|
||||||
if let Some(window) = handle::Handle::get_window() {
|
if let Some(window) = WindowManager::get_main_window() {
|
||||||
let handler_id = window.listen("tauri://focus", move |_event| {
|
let handler_id = window.listen("tauri://focus", move |_event| {
|
||||||
logging_error!(Type::Lightweight, cancel_light_weight_timer());
|
logging_error!(Type::Lightweight, cancel_light_weight_timer());
|
||||||
logging!(debug, Type::Lightweight, "监听到窗口获得焦点,取消轻量模式计时");
|
logging!(debug, Type::Lightweight, "监听到窗口获得焦点,取消轻量模式计时");
|
||||||
@ -181,7 +181,7 @@ fn setup_webview_focus_listener() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cancel_webview_focus_listener() {
|
fn cancel_webview_focus_listener() {
|
||||||
if let Some(window) = handle::Handle::get_window() {
|
if let Some(window) = WindowManager::get_main_window() {
|
||||||
let id = WEBVIEW_FOCUS_HANDLER_ID.swap(0, Ordering::AcqRel);
|
let id = WEBVIEW_FOCUS_HANDLER_ID.swap(0, Ordering::AcqRel);
|
||||||
if id != 0 {
|
if id != 0 {
|
||||||
window.unlisten(id);
|
window.unlisten(id);
|
||||||
|
|||||||
@ -59,6 +59,28 @@ fn should_handle_window_operation() -> bool {
|
|||||||
pub struct WindowManager;
|
pub struct WindowManager;
|
||||||
|
|
||||||
impl WindowManager {
|
impl WindowManager {
|
||||||
|
pub fn get_main_window_with_state() -> (Option<WebviewWindow<Wry>>, WindowState) {
|
||||||
|
let Some(window) = Self::get_main_window() else {
|
||||||
|
return (None, WindowState::NotExist);
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_minimized = window.is_minimized().unwrap_or(false);
|
||||||
|
let is_visible = window.is_visible().unwrap_or(false);
|
||||||
|
let is_focused = window.is_focused().unwrap_or(false);
|
||||||
|
|
||||||
|
let state = if is_minimized {
|
||||||
|
WindowState::Minimized
|
||||||
|
} else if !is_visible {
|
||||||
|
WindowState::Hidden
|
||||||
|
} else if is_focused {
|
||||||
|
WindowState::VisibleFocused
|
||||||
|
} else {
|
||||||
|
WindowState::VisibleUnfocused
|
||||||
|
};
|
||||||
|
|
||||||
|
(Some(window), state)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_main_window_state() -> WindowState {
|
pub fn get_main_window_state() -> WindowState {
|
||||||
match Self::get_main_window() {
|
match Self::get_main_window() {
|
||||||
Some(window) => {
|
Some(window) => {
|
||||||
@ -119,12 +141,12 @@ impl WindowManager {
|
|||||||
WindowOperationResult::NoAction
|
WindowOperationResult::NoAction
|
||||||
}
|
}
|
||||||
WindowState::VisibleUnfocused | WindowState::Minimized | WindowState::Hidden => {
|
WindowState::VisibleUnfocused | WindowState::Minimized | WindowState::Hidden => {
|
||||||
if let Some(window) = Self::get_main_window() {
|
let (window, state_after_check) = Self::get_main_window_with_state();
|
||||||
let state_after_check = Self::get_main_window_state();
|
if state_after_check == WindowState::VisibleFocused {
|
||||||
if state_after_check == WindowState::VisibleFocused {
|
logging!(info, Type::Window, "窗口在检查期间已变为可见和有焦点状态");
|
||||||
logging!(info, Type::Window, "窗口在检查期间已变为可见和有焦点状态");
|
return WindowOperationResult::NoAction;
|
||||||
return WindowOperationResult::NoAction;
|
}
|
||||||
}
|
if let Some(window) = window {
|
||||||
Self::activate_window(&window)
|
Self::activate_window(&window)
|
||||||
} else {
|
} else {
|
||||||
WindowOperationResult::Failed
|
WindowOperationResult::Failed
|
||||||
@ -135,25 +157,18 @@ impl WindowManager {
|
|||||||
|
|
||||||
/// 切换主窗口显示状态(显示/隐藏)
|
/// 切换主窗口显示状态(显示/隐藏)
|
||||||
pub async fn toggle_main_window() -> WindowOperationResult {
|
pub async fn toggle_main_window() -> WindowOperationResult {
|
||||||
// 防抖检查
|
|
||||||
if !should_handle_window_operation() {
|
if !should_handle_window_operation() {
|
||||||
return WindowOperationResult::NoAction;
|
return WindowOperationResult::NoAction;
|
||||||
};
|
}
|
||||||
logging!(info, Type::Window, "开始切换主窗口显示状态");
|
|
||||||
|
|
||||||
let current_state = Self::get_main_window_state();
|
let (window, state) = Self::get_main_window_with_state();
|
||||||
logging!(
|
|
||||||
info,
|
|
||||||
Type::Window,
|
|
||||||
"当前窗口状态: {:?} | 详细状态: {}",
|
|
||||||
current_state,
|
|
||||||
Self::get_window_status_info()
|
|
||||||
);
|
|
||||||
|
|
||||||
match current_state {
|
logging!(debug, Type::Window, "当前状态: {:?}", state);
|
||||||
|
|
||||||
|
match state {
|
||||||
WindowState::NotExist => Self::handle_not_exist_toggle().await,
|
WindowState::NotExist => Self::handle_not_exist_toggle().await,
|
||||||
WindowState::VisibleFocused | WindowState::VisibleUnfocused => Self::hide_main_window(),
|
WindowState::VisibleFocused | WindowState::VisibleUnfocused => Self::hide_main_window(window.as_ref()),
|
||||||
WindowState::Minimized | WindowState::Hidden => Self::activate_existing_main_window(),
|
WindowState::Minimized | WindowState::Hidden => Self::activate_existing_main_window(window.as_ref()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,9 +184,9 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏主窗口
|
// 隐藏主窗口
|
||||||
fn hide_main_window() -> WindowOperationResult {
|
fn hide_main_window(window: Option<&WebviewWindow<Wry>>) -> WindowOperationResult {
|
||||||
logging!(info, Type::Window, "窗口可见,将隐藏窗口");
|
logging!(info, Type::Window, "窗口可见,将隐藏窗口");
|
||||||
if let Some(window) = Self::get_main_window() {
|
if let Some(window) = window {
|
||||||
match window.hide() {
|
match window.hide() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
logging!(info, Type::Window, "窗口已成功隐藏");
|
logging!(info, Type::Window, "窗口已成功隐藏");
|
||||||
@ -189,10 +204,10 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 激活已存在的主窗口
|
// 激活已存在的主窗口
|
||||||
fn activate_existing_main_window() -> WindowOperationResult {
|
fn activate_existing_main_window(window: Option<&WebviewWindow<Wry>>) -> WindowOperationResult {
|
||||||
logging!(info, Type::Window, "窗口存在但被隐藏或最小化,将激活窗口");
|
logging!(info, Type::Window, "窗口存在但被隐藏或最小化,将激活窗口");
|
||||||
if let Some(window) = Self::get_main_window() {
|
if let Some(window) = window {
|
||||||
Self::activate_window(&window)
|
Self::activate_window(window)
|
||||||
} else {
|
} else {
|
||||||
logging!(warn, Type::Window, "无法获取窗口实例");
|
logging!(warn, Type::Window, "无法获取窗口实例");
|
||||||
WindowOperationResult::Failed
|
WindowOperationResult::Failed
|
||||||
@ -255,24 +270,18 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 检查窗口是否可见
|
/// 检查窗口是否可见
|
||||||
pub fn is_main_window_visible() -> bool {
|
pub fn is_main_window_visible(window: Option<&WebviewWindow<Wry>>) -> bool {
|
||||||
Self::get_main_window()
|
window.map(|w| w.is_visible().unwrap_or(false)).unwrap_or(false)
|
||||||
.map(|window| window.is_visible().unwrap_or(false))
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 检查窗口是否有焦点
|
/// 检查窗口是否有焦点
|
||||||
pub fn is_main_window_focused() -> bool {
|
pub fn is_main_window_focused(window: Option<&WebviewWindow<Wry>>) -> bool {
|
||||||
Self::get_main_window()
|
window.map(|w| w.is_focused().unwrap_or(false)).unwrap_or(false)
|
||||||
.map(|window| window.is_focused().unwrap_or(false))
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 检查窗口是否最小化
|
/// 检查窗口是否最小化
|
||||||
pub fn is_main_window_minimized() -> bool {
|
pub fn is_main_window_minimized(window: Option<&WebviewWindow<Wry>>) -> bool {
|
||||||
Self::get_main_window()
|
window.map(|w| w.is_minimized().unwrap_or(false)).unwrap_or(false)
|
||||||
.map(|window| window.is_minimized().unwrap_or(false))
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建新窗口,防抖避免重复调用
|
/// 创建新窗口,防抖避免重复调用
|
||||||
@ -320,11 +329,11 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 获取详细的窗口状态信息
|
/// 获取详细的窗口状态信息
|
||||||
pub fn get_window_status_info() -> String {
|
fn get_window_status_info() -> String {
|
||||||
let state = Self::get_main_window_state();
|
let (window, state) = Self::get_main_window_with_state();
|
||||||
let is_visible = Self::is_main_window_visible();
|
let is_visible = Self::is_main_window_visible(window.as_ref());
|
||||||
let is_focused = Self::is_main_window_focused();
|
let is_focused = Self::is_main_window_focused(window.as_ref());
|
||||||
let is_minimized = Self::is_main_window_minimized();
|
let is_minimized = Self::is_main_window_minimized(window.as_ref());
|
||||||
|
|
||||||
format!("窗口状态: {state:?} | 可见: {is_visible} | 有焦点: {is_focused} | 最小化: {is_minimized}")
|
format!("窗口状态: {state:?} | 可见: {is_visible} | 有焦点: {is_focused} | 最小化: {is_minimized}")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,11 @@ import useSWR, { mutate } from "swr";
|
|||||||
import { selectNodeForGroup } from "tauri-plugin-mihomo-api";
|
import { selectNodeForGroup } from "tauri-plugin-mihomo-api";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
calcuProxies,
|
||||||
getProfiles,
|
getProfiles,
|
||||||
patchProfile,
|
patchProfile,
|
||||||
patchProfilesConfig,
|
patchProfilesConfig,
|
||||||
} from "@/services/cmds";
|
} from "@/services/cmds";
|
||||||
import { calcuProxies } from "@/services/cmds";
|
|
||||||
import { debugLog } from "@/utils/debug";
|
import { debugLog } from "@/utils/debug";
|
||||||
|
|
||||||
export const useProfiles = () => {
|
export const useProfiles = () => {
|
||||||
@ -36,6 +36,7 @@ export const useProfiles = () => {
|
|||||||
const patchProfiles = async (
|
const patchProfiles = async (
|
||||||
value: Partial<IProfilesConfig>,
|
value: Partial<IProfilesConfig>,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
|
options?: { deferRefreshOnSuccess?: boolean },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
if (signal?.aborted) {
|
if (signal?.aborted) {
|
||||||
@ -47,7 +48,9 @@ export const useProfiles = () => {
|
|||||||
throw new DOMException("Operation was aborted", "AbortError");
|
throw new DOMException("Operation was aborted", "AbortError");
|
||||||
}
|
}
|
||||||
|
|
||||||
await mutateProfiles();
|
if (!options?.deferRefreshOnSuccess || !success) {
|
||||||
|
await mutateProfiles();
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -70,16 +73,14 @@ export const useProfiles = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 根据selected的节点选择
|
// 根据selected的节点选择
|
||||||
const activateSelected = async () => {
|
const activateSelected = async (profileOverride?: IProfilesConfig) => {
|
||||||
try {
|
try {
|
||||||
debugLog("[ActivateSelected] 开始处理代理选择");
|
debugLog("[ActivateSelected] 开始处理代理选择");
|
||||||
|
|
||||||
const [proxiesData, profileData] = await Promise.all([
|
const proxiesData = await calcuProxies();
|
||||||
calcuProxies(),
|
const profileData = profileOverride ?? profiles;
|
||||||
getProfiles(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!profileData || !proxiesData) {
|
if (!profileData || !proxiesData || !profileData.items) {
|
||||||
debugLog("[ActivateSelected] 代理或配置数据不可用,跳过处理");
|
debugLog("[ActivateSelected] 代理或配置数据不可用,跳过处理");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -389,7 +389,7 @@ const ProfilePage = () => {
|
|||||||
switchingProfileRef.current === profile &&
|
switchingProfileRef.current === profile &&
|
||||||
!abortController.signal.aborted
|
!abortController.signal.aborted
|
||||||
) {
|
) {
|
||||||
await activateSelected();
|
await activateSelected(profiles);
|
||||||
debugLog(`[Profile] 后台处理完成,序列号: ${sequence}`);
|
debugLog(`[Profile] 后台处理完成,序列号: ${sequence}`);
|
||||||
} else {
|
} else {
|
||||||
debugProfileSwitch(
|
debugProfileSwitch(
|
||||||
@ -402,7 +402,7 @@ const ProfilePage = () => {
|
|||||||
console.warn("Failed to activate selected proxies:", err);
|
console.warn("Failed to activate selected proxies:", err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[activateSelected],
|
[activateSelected, profiles],
|
||||||
);
|
);
|
||||||
|
|
||||||
const activateProfile = useCallback(
|
const activateProfile = useCallback(
|
||||||
@ -456,6 +456,7 @@ const ProfilePage = () => {
|
|||||||
const requestPromise = patchProfiles(
|
const requestPromise = patchProfiles(
|
||||||
{ current: profile },
|
{ current: profile },
|
||||||
currentAbortController.signal,
|
currentAbortController.signal,
|
||||||
|
{ deferRefreshOnSuccess: true },
|
||||||
);
|
);
|
||||||
pendingRequestRef.current = requestPromise;
|
pendingRequestRef.current = requestPromise;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export async function enhanceProfiles() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function patchProfilesConfig(profiles: IProfilesConfig) {
|
export async function patchProfilesConfig(profiles: IProfilesConfig) {
|
||||||
return invoke<void>("patch_profiles_config", { profiles });
|
return invoke<boolean>("patch_profiles_config", { profiles });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createProfile(
|
export async function createProfile(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user