From c5233a9c2c92c3a3a93189f7fd345b086c8d1866 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:47:36 +0800 Subject: [PATCH] perf: refactor PrfOption merge logic and streamline update_item method in IProfiles --- src-tauri/src/config/prfitem.rs | 35 ++++++++++----------- src-tauri/src/config/profiles.rs | 54 ++++++++++++++------------------ 2 files changed, 39 insertions(+), 50 deletions(-) diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index e888a80ef..b06060b51 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -124,25 +124,22 @@ pub struct PrfOption { impl PrfOption { pub fn merge(one: Option<&Self>, other: Option<&Self>) -> Option { match (one, other) { - (Some(a_ref), Some(b_ref)) => { - let mut result = a_ref.clone(); - result.user_agent = b_ref.user_agent.clone().or(result.user_agent); - result.with_proxy = b_ref.with_proxy.or(result.with_proxy); - result.self_proxy = b_ref.self_proxy.or(result.self_proxy); - result.danger_accept_invalid_certs = - b_ref.danger_accept_invalid_certs.or(result.danger_accept_invalid_certs); - result.allow_auto_update = b_ref.allow_auto_update.or(result.allow_auto_update); - result.update_interval = b_ref.update_interval.or(result.update_interval); - result.merge = b_ref.merge.clone().or(result.merge); - result.script = b_ref.script.clone().or(result.script); - result.rules = b_ref.rules.clone().or(result.rules); - result.proxies = b_ref.proxies.clone().or(result.proxies); - result.groups = b_ref.groups.clone().or(result.groups); - result.timeout_seconds = b_ref.timeout_seconds.or(result.timeout_seconds); - Some(result) - } - (Some(a_ref), None) => Some(a_ref.clone()), - (None, Some(b_ref)) => Some(b_ref.clone()), + (Some(a), Some(b)) => Some(Self { + user_agent: b.user_agent.as_ref().or(a.user_agent.as_ref()).cloned(), + with_proxy: b.with_proxy.or(a.with_proxy), + self_proxy: b.self_proxy.or(a.self_proxy), + danger_accept_invalid_certs: b.danger_accept_invalid_certs.or(a.danger_accept_invalid_certs), + allow_auto_update: b.allow_auto_update.or(a.allow_auto_update), + update_interval: b.update_interval.or(a.update_interval), + merge: b.merge.as_ref().or(a.merge.as_ref()).cloned(), + script: b.script.as_ref().or(a.script.as_ref()).cloned(), + rules: b.rules.as_ref().or(a.rules.as_ref()).cloned(), + proxies: b.proxies.as_ref().or(a.proxies.as_ref()).cloned(), + groups: b.groups.as_ref().or(a.groups.as_ref()).cloned(), + timeout_seconds: b.timeout_seconds.or(a.timeout_seconds), + }), + (Some(a), None) => Some(a.clone()), + (None, Some(b)) => Some(b.clone()), (None, None) => None, } } diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index 0d559b34a..3ed7dfc6c 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -217,43 +217,35 @@ impl IProfiles { /// be used to update the remote item /// only patch `updated` `extra` `file_data` pub async fn update_item(&mut self, uid: &String, item: &mut PrfItem) -> Result<()> { - if self.items.is_none() { - self.items = Some(vec![]); - } + let target = self + .items + .get_or_insert_default() + .iter_mut() + .find(|each| each.uid.as_ref() == Some(uid)) + .ok_or_else(|| anyhow::anyhow!("Item not found"))?; - // find the item - let _ = self.get_item(uid)?; + target.extra = item.extra; + target.updated = item.updated; + target.home = std::mem::take(&mut item.home); + target.option = PrfOption::merge(target.option.as_ref(), item.option.as_ref()); - if let Some(items) = self.items.as_mut() { - let some_uid = Some(uid.clone()); + let Some(file_data) = item.file_data.take() else { + return self.save_file().await; + }; - for each in items.iter_mut() { - if each.uid == some_uid { - each.extra = item.extra; - each.updated = item.updated; - each.home = item.home.to_owned(); - each.option = PrfOption::merge(each.option.as_ref(), item.option.as_ref()); - // save the file data - // move the field value after save - if let Some(file_data) = item.file_data.take() { - let file = each.file.take(); - let file = - file.unwrap_or_else(|| item.file.take().unwrap_or_else(|| format!("{}.yaml", &uid).into())); + let file = target + .file + .take() + .or_else(|| item.file.take()) + .unwrap_or_else(|| format!("{}.yaml", uid).into()); - // the file must exists - each.file = Some(file.clone()); + let path = dirs::app_profiles_dir()?.join(file.as_str()); - let path = dirs::app_profiles_dir()?.join(file.as_str()); + fs::write(&path, file_data.as_bytes()) + .await + .with_context(|| format!("failed to write to file \"{file}\""))?; - fs::write(&path, file_data.as_bytes()) - .await - .with_context(|| format!("failed to write to file \"{file}\""))?; - } - - break; - } - } - } + target.file = Some(file); self.save_file().await }