From d5471bb36cfa5a177fc31f1a8a564a6d8b5d94a1 Mon Sep 17 00:00:00 2001 From: Ap_Tx <3045929398@qq.com> Date: Fri, 2 Oct 2026 19:16:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20feature=5Fflags=20=E5=8F=8D=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96=E5=BF=BD=E7=95=A5=E6=9C=AA=E7=9F=A5=E5=BC=80?= =?UTF-8?q?=E5=85=B3=EF=BC=8C=E9=81=BF=E5=85=8D=E5=89=8D=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE=E4=B8=8D=E5=90=8C=E6=AD=A5=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/app-lib/src/state/settings.rs | 42 ++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/app-lib/src/state/settings.rs b/packages/app-lib/src/state/settings.rs index 13419ae..f40435e 100644 --- a/packages/app-lib/src/state/settings.rs +++ b/packages/app-lib/src/state/settings.rs @@ -181,6 +181,7 @@ pub struct Settings { pub migrated: bool, pub developer_mode: bool, + #[serde(deserialize_with = "deserialize_feature_flags")] pub feature_flags: HashMap, pub skipped_update: Option, @@ -222,6 +223,43 @@ pub enum FeatureFlag { AutoInstallDependencies, } +/// 反序列化 feature flags,遇到未知的 flag 名称时直接忽略,而不是报错。 +/// +/// 这样即使前端(或更新的版本)写入了当前后端不认识的 flag, +/// 旧版本也能正常读取设置,而不是整包失败导致启动器初始化崩溃。 +fn deserialize_feature_flags<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let raw = HashMap::::deserialize(deserializer)?; + Ok(filter_known_feature_flags(raw)) +} + +/// 从 JSON 字符串解析 feature flags,忽略未知名称。 +fn parse_feature_flags_json(value: &str) -> HashMap { + match serde_json::from_str::>(value) { + Ok(raw) => filter_known_feature_flags(raw), + Err(_) => HashMap::new(), + } +} + +/// 只保留能解析为 [`FeatureFlag`] 的条目,未知名称静默丢弃。 +fn filter_known_feature_flags( + raw: HashMap, +) -> HashMap { + let mut flags = HashMap::with_capacity(raw.len()); + for (key, value) in raw { + if let Ok(flag) = + serde_json::from_value::(serde_json::Value::String(key)) + { + flags.insert(flag, value); + } + } + flags +} + impl Settings { const CURRENT_VERSION: usize = 3; @@ -384,8 +422,8 @@ impl Settings { migrated: res.migrated == 1, feature_flags: res .feature_flags - .as_ref() - .and_then(|x| serde_json::from_str(x).ok()) + .as_deref() + .map(parse_feature_flags_json) .unwrap_or_default(), skipped_update: res.skipped_update, pending_update_toast_for_version: res