From 4adac9e4b6fe19298a9d9fe3a0e1c45e00f95d85 Mon Sep 17 00:00:00 2001 From: sdhfsl Date: Wed, 11 Nov 2026 17:33:03 +0000 Subject: [PATCH] fix(config): stop rewriting unchanged configs on exit (#8017) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(config): stop rewriting unchanged configs on exit apply_all_and_save_file() committed the drafts and then saved clash.yaml, verge.yaml and profiles.yaml unconditionally. With nothing staged that write replaced each file with content equal to what was already on disk - fields are encrypted with a fresh nonce, so the bytes differ every time - which reset the files' creation time on every exit (#7759). Draft::apply now reports whether it committed a draft, and the exit path saves only the configs that had one. * refactor(tests): remove test snippets Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> * docs(changelog): add entry of the PR modifications Assisted-by: Gemini 3.8 Flash Medium (VSCode Copilot Chat) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --------- Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> Co-authored-by: sdhfsl Co-authored-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Changelog.md | 2 ++ crates/clash-verge-draft/src/lib.rs | 12 ++++++++---- src-tauri/src/config/config.rs | 16 ++++++++++------ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Changelog.md b/Changelog.md index e53b4ebf3..b8e9235b9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -24,6 +24,8 @@
🐞 修复问题 +- 修复应用退出时无条件重写 `clash.yaml`、`verge.yaml` 和 `profiles.yaml` 导致文件创建时间丢失的问题 + - 修复检测更新后又发布新版时,应用内更新失败 - 修复订阅响应过大导致内存占用过高,限制单次下载为 4 MiB - 修复全局模式默认停在 `DIRECT` 或 `REJECT` 导致流量未经代理,现自动切换到第一个策略组 diff --git a/crates/clash-verge-draft/src/lib.rs b/crates/clash-verge-draft/src/lib.rs index c9bf560e5..0dcf1c5a6 100644 --- a/crates/clash-verge-draft/src/lib.rs +++ b/crates/clash-verge-draft/src/lib.rs @@ -74,12 +74,16 @@ impl Draft { result } - /// Commits and clears the draft. + /// Commits and clears the draft, reporting whether one was staged. #[inline] - pub fn apply(&self) { + pub fn apply(&self) -> bool { let mut guard = self.inner.data.lock(); - if let Some(d) = guard.1.take() { - guard.0 = d; + match guard.1.take() { + Some(d) => { + guard.0 = d; + true + } + None => false, } } diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs index 59e6f921d..a0cb4191d 100644 --- a/src-tauri/src/config/config.rs +++ b/src-tauri/src/config/config.rs @@ -280,25 +280,29 @@ impl Config { } /// Commits drafts during exit/restart/shutdown so user changes are not lost. + /// A config with nothing staged keeps its file, so its timestamps stay put. pub async fn apply_all_and_save_file() { logging!(debug, Type::Config, "save all draft data"); let save_clash_task = AsyncHandler::spawn(|| async { let clash = Self::clash().await; - clash.apply(); - logging_error!(Type::Config, clash.data_arc().save_config().await); + if clash.apply() { + logging_error!(Type::Config, clash.data_arc().save_config().await); + } }); let save_verge_task = AsyncHandler::spawn(|| async { let verge = Self::verge().await; - verge.apply(); - logging_error!(Type::Config, verge.data_arc().save_file().await); + if verge.apply() { + logging_error!(Type::Config, verge.data_arc().save_file().await); + } }); let save_profiles_task = AsyncHandler::spawn(|| async { let _profile_write = super::profiles::PROFILE_WRITE_LOCK.lock().await; let profiles = Self::profiles().await; - profiles.apply(); - logging_error!(Type::Config, profiles.data_arc().save_file().await); + if profiles.apply() { + logging_error!(Type::Config, profiles.data_arc().save_file().await); + } }); let _ = tokio::join!(save_clash_task, save_verge_task, save_profiles_task);