feat(profiles): add profile preview structure and update profile menu handling

This commit is contained in:
Tunglies
2025-11-18 19:08:07 +08:00
parent ec7f912eae
commit 3ec7c6d2b8
3 changed files with 37 additions and 32 deletions

View File

@@ -31,6 +31,7 @@
- 优化备份设置布局 - 优化备份设置布局
- 优化流量图性能表现,实现动态 FPS 和窗口失焦自动暂停 - 优化流量图性能表现,实现动态 FPS 和窗口失焦自动暂停
- 性能优化系统状态获取 - 性能优化系统状态获取
- 优化托盘菜单当前订阅检测逻辑
</details> </details>

View File

@@ -21,6 +21,12 @@ pub struct IProfiles {
pub items: Option<Vec<PrfItem>>, pub items: Option<Vec<PrfItem>>,
} }
pub struct IProfilePreview<'a> {
pub uid: &'a String,
pub name: &'a String,
pub is_current: bool,
}
/// 清理结果 /// 清理结果
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CleanupResult { pub struct CleanupResult {
@@ -367,14 +373,20 @@ impl IProfiles {
self.current.as_ref() == Some(index) self.current.as_ref() == Some(index)
} }
/// 获取所有的profiles(uid名称) /// 获取所有的profiles(uid名称, 是否为 current)
pub fn all_profile_uid_and_name(&self) -> Option<Vec<(&String, &String)>> { pub fn profiles_preview(&self) -> Option<Vec<IProfilePreview<'_>>> {
self.items.as_ref().map(|items| { self.items.as_ref().map(|items| {
items items
.iter() .iter()
.filter_map(|e| { .filter_map(|e| {
if let (Some(uid), Some(name)) = (e.uid.as_ref(), e.name.as_ref()) { if let (Some(uid), Some(name)) = (e.uid.as_ref(), e.name.as_ref()) {
Some((uid, name)) let is_current = self.is_current_profile_index(uid);
let preview = IProfilePreview {
uid,
name,
is_current,
};
Some(preview)
} else { } else {
None None
} }

View File

@@ -4,7 +4,7 @@ use tauri_plugin_mihomo::models::Proxies;
use tokio::fs; use tokio::fs;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub mod speed_rate; pub mod speed_rate;
use crate::config::{IVerge, PrfSelected}; use crate::config::{IProfilePreview, IVerge, PrfSelected};
use crate::core::service; use crate::core::service;
use crate::module::lightweight; use crate::module::lightweight;
use crate::process::AsyncHandler; use crate::process::AsyncHandler;
@@ -20,7 +20,6 @@ use crate::{
use super::handle; use super::handle;
use anyhow::Result; use anyhow::Result;
use futures::future::join_all;
use parking_lot::Mutex; use parking_lot::Mutex;
use smartstring::alias::String; use smartstring::alias::String;
use std::collections::HashMap; use std::collections::HashMap;
@@ -315,7 +314,7 @@ impl Tray {
}; };
let profiles_config = Config::profiles().await; let profiles_config = Config::profiles().await;
let profiles_arc = profiles_config.latest_arc(); let profiles_arc = profiles_config.latest_arc();
let profile_uid_and_name = profiles_arc.all_profile_uid_and_name().unwrap_or_default(); let profiles_preview = profiles_arc.profiles_preview().unwrap_or_default();
let is_lightweight_mode = is_in_lightweight_mode(); let is_lightweight_mode = is_in_lightweight_mode();
match app_handle.tray_by_id("main") { match app_handle.tray_by_id("main") {
@@ -327,7 +326,7 @@ impl Tray {
*system_proxy, *system_proxy,
*tun_mode, *tun_mode,
tun_mode_available, tun_mode_available,
profile_uid_and_name, profiles_preview,
is_lightweight_mode, is_lightweight_mode,
) )
.await?, .await?,
@@ -607,31 +606,24 @@ fn create_hotkeys(hotkeys: &Option<Vec<String>>) -> HashMap<String, String> {
.unwrap_or_default() .unwrap_or_default()
} }
async fn create_profile_menu_item( fn create_profile_menu_item(
app_handle: &AppHandle, app_handle: &AppHandle,
profile_uid_and_name: Vec<(&String, &String)>, profiles_preview: Vec<IProfilePreview<'_>>,
) -> Result<Vec<CheckMenuItem<Wry>>> { ) -> Result<Vec<CheckMenuItem<Wry>>> {
let futures = profile_uid_and_name profiles_preview
.iter() .into_iter()
.map(|(profile_uid, profile_name)| { .map(|profile| {
let app_handle = app_handle.clone(); CheckMenuItem::with_id(
async move { app_handle,
let is_current_profile = Config::profiles() format!("profiles_{}", profile.uid),
.await profile.name,
.latest_arc() true,
.is_current_profile_index(profile_uid); profile.is_current,
CheckMenuItem::with_id( None::<&str>,
&app_handle, )
format!("profiles_{profile_uid}"), .map_err(|e| e.into())
profile_name.as_str(), })
true, .collect()
is_current_profile,
None::<&str>,
)
}
});
let results = join_all(futures).await;
Ok(results.into_iter().collect::<Result<Vec<_>, _>>()?)
} }
fn create_subcreate_proxy_menu_item( fn create_subcreate_proxy_menu_item(
@@ -813,7 +805,7 @@ async fn create_tray_menu(
system_proxy_enabled: bool, system_proxy_enabled: bool,
tun_mode_enabled: bool, tun_mode_enabled: bool,
tun_mode_available: bool, tun_mode_available: bool,
profile_uid_and_name: Vec<(&String, &String)>, profiles_preview: Vec<IProfilePreview<'_>>,
is_lightweight_mode: bool, is_lightweight_mode: bool,
) -> Result<tauri::menu::Menu<Wry>> { ) -> Result<tauri::menu::Menu<Wry>> {
let current_proxy_mode = mode.unwrap_or(""); let current_proxy_mode = mode.unwrap_or("");
@@ -877,7 +869,7 @@ async fn create_tray_menu(
let hotkeys = create_hotkeys(&verge_settings.hotkeys); let hotkeys = create_hotkeys(&verge_settings.hotkeys);
let profile_menu_items: Vec<CheckMenuItem<Wry>> = let profile_menu_items: Vec<CheckMenuItem<Wry>> =
create_profile_menu_item(app_handle, profile_uid_and_name).await?; create_profile_menu_item(app_handle, profiles_preview)?;
// Pre-fetch all localized strings // Pre-fetch all localized strings
let texts = MenuTexts::new(); let texts = MenuTexts::new();