mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
perf: refactor PrfOption merge logic and streamline update_item method in IProfiles
This commit is contained in:
@@ -124,25 +124,22 @@ pub struct PrfOption {
|
||||
impl PrfOption {
|
||||
pub fn merge(one: Option<&Self>, other: Option<&Self>) -> Option<Self> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user