diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index 24dc7eb77..e888a80ef 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -60,13 +60,13 @@ pub struct PrfItem { pub file_data: Option, } -#[derive(Default, Debug, Clone, Deserialize, Serialize)] +#[derive(Default, Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct PrfSelected { pub name: Option, pub now: Option, } -#[derive(Default, Debug, Clone, Copy, Deserialize, Serialize)] +#[derive(Default, Debug, Clone, Copy, PartialEq, Deserialize, Serialize)] pub struct PrfExtra { pub upload: u64, pub download: u64, diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index e97525c16..0d559b34a 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -37,8 +37,10 @@ pub struct CleanupResult { macro_rules! patch { ($lv: expr, $rv: expr, $key: tt) => { - if ($rv.$key).is_some() { - $lv.$key = $rv.$key.to_owned(); + if let Some(ref val) = $rv.$key { + if Some(val) != $lv.$key.as_ref() { + $lv.$key = Some(val.to_owned()); + } } }; } @@ -53,21 +55,22 @@ impl IProfiles { } }; - match help::read_yaml::(&path).await { - Ok(mut profiles) => { - let items = profiles.items.get_or_insert_with(Vec::new); - for item in items.iter_mut() { - if item.uid.is_none() { - item.uid = Some(help::get_uid("d").into()); - } - } - profiles - } + let mut profiles = match help::read_yaml::(&path).await { + Ok(profiles) => profiles, Err(err) => { logging!(error, Type::Config, "{err}"); - Self::default() + return Self::default(); + } + }; + + let items = profiles.items.get_or_insert_with(Vec::new); + for item in items.iter_mut() { + if item.uid.is_none() { + item.uid = Some(help::get_uid("d").into()); } } + + profiles } pub async fn save_file(&self) -> Result<()> { @@ -103,38 +106,28 @@ impl IProfiles { pub fn get_item(&self, uid: impl AsRef) -> Result<&PrfItem> { let uid_str = uid.as_ref(); - if let Some(items) = self.items.as_ref() { - for each in items.iter() { - if let Some(uid_val) = &each.uid - && uid_val.as_str() == uid_str - { - return Ok(each); - } - } - } - - bail!("failed to get the profile item \"uid:{}\"", uid_str); + self.items + .as_ref() + .ok_or_else(|| anyhow::anyhow!("no profile items found"))? + .iter() + .find(|each| each.uid.as_ref().is_some_and(|uid_val| uid_val.as_str() == uid_str)) + .ok_or_else(|| anyhow::anyhow!("failed to get the profile item \"uid:{}\"", uid_str)) } /// append new item /// if the file_data is some /// then should save the data to file pub async fn append_item(&mut self, item: &mut PrfItem) -> Result<()> { - let uid = &item.uid; - if uid.is_none() { - bail!("the uid should not be null"); - } + anyhow::ensure!(item.uid.is_some(), "the uid should not be null"); // save the file data // move the field value after save if let Some(file_data) = item.file_data.take() { - if item.file.is_none() { - bail!("the file should not be null"); - } + anyhow::ensure!(item.file.is_some(), "the file should not be null"); let file = item .file - .clone() + .as_ref() .ok_or_else(|| anyhow::anyhow!("file field is required when file_data is provided"))?; let path = dirs::app_profiles_dir()?.join(file.as_str()); @@ -143,17 +136,14 @@ impl IProfiles { .with_context(|| format!("failed to write to file \"{file}\""))?; } - if self.current.is_none() && (item.itype == Some("remote".into()) || item.itype == Some("local".into())) { - self.current = uid.to_owned(); + if self.current.is_none() + && let Some(t) = item.itype.as_deref() + && (t == "remote" || t == "local") + { + self.current = item.uid.to_owned(); } - if self.items.is_none() { - self.items = Some(vec![]); - } - - if let Some(items) = self.items.as_mut() { - items.push(item.to_owned()); - } + self.items.get_or_insert_default().push(std::mem::take(item)); Ok(()) } @@ -200,26 +190,27 @@ impl IProfiles { /// update the item value pub async fn patch_item(&mut self, uid: &String, item: &PrfItem) -> Result<()> { - let mut items = self.items.take().unwrap_or_default(); + let items = self + .items + .as_mut() + .ok_or_else(|| anyhow::anyhow!("no profile items found"))?; - for each in items.iter_mut() { - if each.uid.as_ref() == Some(uid) { - patch!(each, item, itype); - patch!(each, item, name); - patch!(each, item, desc); - patch!(each, item, file); - patch!(each, item, url); - patch!(each, item, selected); - patch!(each, item, extra); - patch!(each, item, updated); - patch!(each, item, option); + let target = items.iter_mut().find(|each| each.uid.as_ref() == Some(uid)); - self.items = Some(items); - return self.save_file().await; - } + if let Some(each) = target { + patch!(each, item, itype); + patch!(each, item, name); + patch!(each, item, desc); + patch!(each, item, file); + patch!(each, item, url); + patch!(each, item, selected); + patch!(each, item, extra); + patch!(each, item, updated); + patch!(each, item, option); + + return self.save_file().await; } - self.items = Some(items); bail!("failed to find the profile item \"uid:{uid}\"") } diff --git a/src-tauri/src/core/timer.rs b/src-tauri/src/core/timer.rs index 5a00b36a9..0b7dc6545 100644 --- a/src-tauri/src/core/timer.rs +++ b/src-tauri/src/core/timer.rs @@ -25,6 +25,7 @@ pub struct TimerTask { pub last_run: i64, // Timestamp of last execution } +// TODO 一个 Timer 负责轻量, 一个 Timer 负责订阅更新。当前会生产 N(订阅数量) + 1 个定时任务 pub struct Timer { /// cron manager pub delay_timer: Arc>,