fix: align draft commit/save semantics

- use committed profiles snapshot for lifecycle saves (avoid persisting uncommitted drafts)
- remove apply/discard calls after profiles with_data_modify helpers
- persist profiles metadata explicitly in create_profile
- apply clash draft before saving mode changes
- surface deep-link profile save failures via logging
This commit is contained in:
Tunglies 2026-03-21 18:38:49 +08:00
parent 85eb3b48c2
commit 70a86b05c5
No known key found for this signature in database
GPG Key ID: B9B01B389469B3E8
4 changed files with 15 additions and 23 deletions

View File

@ -46,7 +46,7 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>>
match CoreManager::global().change_core(&clash_core).await {
Ok(_) => {
logging_error!(Type::Core, Config::profiles().await.latest_arc().save_file().await);
logging_error!(Type::Core, Config::profiles().await.data_arc().save_file().await);
// 切换内核后重启内核
match CoreManager::global().restart_core().await {
@ -86,7 +86,7 @@ pub async fn start_core() -> CmdResult {
/// 关闭核心
#[tauri::command]
pub async fn stop_core() -> CmdResult {
logging_error!(Type::Core, Config::profiles().await.latest_arc().save_file().await);
logging_error!(Type::Core, Config::profiles().await.data_arc().save_file().await);
let result = CoreManager::global().stop_core().await.stringify_err();
if result.is_ok() {
handle::Handle::refresh_clash();
@ -97,7 +97,7 @@ pub async fn stop_core() -> CmdResult {
/// 重启核心
#[tauri::command]
pub async fn restart_core() -> CmdResult {
logging_error!(Type::Core, Config::profiles().await.latest_arc().save_file().await);
logging_error!(Type::Core, Config::profiles().await.data_arc().save_file().await);
let result = CoreManager::global().restart_core().await.stringify_err();
if result.is_ok() {
handle::Handle::refresh_clash();

View File

@ -116,11 +116,9 @@ pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult {
match profiles_reorder_safe(&active_id, &over_id).await {
Ok(_) => {
logging!(info, Type::Cmd, "重新排序配置文件");
Config::profiles().await.apply();
Ok(())
}
Err(err) => {
Config::profiles().await.discard();
logging!(error, Type::Cmd, "重新排序配置文件失败: {}", err);
Err(format!("重新排序配置文件失败: {}", err).into())
}
@ -133,21 +131,18 @@ pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult {
pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResult {
match profiles_append_item_with_filedata_safe(&item, file_data).await {
Ok(_) => {
profiles_save_file_safe().await.stringify_err()?;
// 发送配置变更通知
if let Some(uid) = &item.uid {
logging!(info, Type::Cmd, "[创建订阅] 发送配置变更通知: {}", uid);
handle::Handle::notify_profile_changed(uid);
}
Config::profiles().await.apply();
Ok(())
}
Err(err) => {
Config::profiles().await.discard();
match err.to_string().as_str() {
"the file already exists" => Err("the file already exists".into()),
_ => Err(format!("add profile error: {err}").into()),
}
}
Err(err) => match err.to_string().as_str() {
"the file already exists" => Err("the file already exists".into()),
_ => Err(format!("add profile error: {err}").into()),
},
}
}
@ -155,12 +150,8 @@ pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResu
#[tauri::command]
pub async fn update_profile(index: String, option: Option<PrfOption>) -> CmdResult {
match feat::update_profile(&index, option.as_ref(), true, true, true).await {
Ok(_) => {
let _: () = Config::profiles().await.apply();
Ok(())
}
Ok(_) => Ok(()),
Err(e) => {
Config::profiles().await.discard();
logging!(error, Type::Cmd, "{}", e);
Err(e.to_string().into())
}
@ -181,7 +172,6 @@ pub async fn delete_profile(index: String) -> CmdResult {
logging!(warn, Type::Cmd, "Warning: 异步更新托盘菜单失败: {e}");
}
if should_update {
Config::profiles().await.apply();
match CoreManager::global().update_config().await {
Ok(_) => {
handle::Handle::refresh_clash();

View File

@ -78,10 +78,12 @@ pub async fn change_clash_mode(mode: String) {
match handle::Handle::mihomo().await.patch_base_config(&json_value).await {
Ok(_) => {
// 更新订阅
Config::clash().await.edit_draft(|d| d.patch_config(&mapping));
let clash = Config::clash().await;
clash.edit_draft(|d| d.patch_config(&mapping));
clash.apply();
// 分离数据获取和异步调用
let clash_data = Config::clash().await.data_arc();
let clash_data = clash.data_arc();
if clash_data.save_config().await.is_ok() {
handle::Handle::refresh_clash();
logging_error!(Type::Tray, tray::Tray::global().update_menu().await);

View File

@ -9,7 +9,7 @@ use crate::{
config::{Config, PrfItem, profiles},
core::{CoreManager, handle},
};
use clash_verge_logging::{Type, logging};
use clash_verge_logging::{Type, logging, logging_error};
pub(super) async fn resolve_scheme(param: &str) -> Result<()> {
logging!(info, Type::Config, "received deep link: {param}");
@ -94,7 +94,7 @@ async fn import_subscription(url: &str, name: Option<&String>) {
}
Config::profiles().await.apply();
let _ = Config::profiles().await.data_arc().save_file().await;
logging_error!(Type::Config, Config::profiles().await.data_arc().save_file().await);
handle::Handle::notice_message(
"import_sub_url::ok",
"", // 空 msg 传入,我们不希望导致 后端-前端-后端 死循环,这里只做提醒。