M201: 接通 iced 设置页的数据通路(下载组:真值 + 真控件 + 写回闭环)

M193 的用户投诉「设置页里改了不生效」的结构性根因是 iced 侧没有设置数据通路:
`CoreEvent::SettingsChanged` 在 `crates/app-iced/src` 零命中、`pages::Model` 没有设置快照、
`download::State` 是空 struct。presenter 那套设置组早就是真值来源(`host::settings::groups`
由 `refresh_all` 与 `dispatch` 的 `SetSetting` 分支发成 `SettingsChanged`),只是没有接到 iced。

这条线现在通了:

    host::settings::groups → SettingsChanged → AppState::settings_groups
      → pages::Model.settings → settings::States.settings → 下载组控件
      → AppCommand::SetSetting → 写盘 + 重新发 SettingsChanged(闭环)

主要改动
- presenter `host/settings/download.rs`:并发/重试两行改成画**引擎生效值**(`DownloadTuning`),
  文件原值与生效值不一致时写明「原值 X 已按出厂 N 生效」(P3-5,两个数都现读);
  gh-proxy 行补「当前生效:跟随内置默认/已关闭/覆盖为 X」。
- app-iced `pages/settings/download.rs`:`GROUP.body = Some(body)`,按 `SettingControl`
  画 choice(filter chip)/ text(输入框 + 应用)/ action(按钮)/ toggle / readonly;写回走
  `app/update/settings/download.rs` → `AppCommand::SetSetting`(不做乐观回显)。
- `pages::Model.settings` + `settings::States.settings`:快照进页面的唯一通道。
- i18n:新增 `SettingsDownloadsApply`(金表锚点追加,`split_keeps_every_translation` 绿)。
- 取证:`ULL_SCREENSHOT_REAL_HOST=1` 让 `--screenshot` 接真 host(截图通道默认强制 mock,
  而 mock 不发 `SettingsChanged`,真值屏拍不出来)。

测试(新增 11 条)
- presenter `download_tests.rs`:P3-5 的越界回落 / 0→1 / 无差异不出提示 + P3-3 的
  gh-proxy 文件→三态端到端链。
- app-iced `app/update/settings/download_tests.rs`:假后端闭环 ×4 + **真 `CoreHost` 端到端**
  (点 16 ⇒ 磁盘上 `launcher.json` 真的有 16)。
- `pages/settings/tests/download_section.rs`:`body.is_none()` 绊线翻成 `is_some()` +
  控件形状 / 空快照不编值。
This commit is contained in:
AskaEth committed 2026-11-09 10:51:16 +08:00
1 parent 0cc1a35420
commit ab573838f3
18 files changed
+1257 -74

No files matched your search

+2
View File
@@ -209,4 +209,6 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("SettingsJavaPrefsSaved", "Saved and read back from disk: all three keys are in the settings file.", "已保存并从磁盘读回:三个键都进配置文件了。"),
("SettingsJavaPrefsUnsaved", "There are unsaved changes in this section.", "这一段有未保存的改动。"),
("SettingsJavaReasonInstallRootTooLong", "the folder path is too long", "目录路径太长"),
// M201:设置页 Downloads 组的文本行提交按钮(装配链里本域紧随 `settings_java_entries`)。
("SettingsDownloadsApply", "Apply", "应用"),
];
+15 -3
View File
@@ -1,11 +1,23 @@
//! 设置页「Downloads」分组文案:**预留**(页面侧的真控件还没接)。
//! 设置页「Downloads」分组文案(M201 起有内容:这一组接了真控件)。
//!
//! 加 key 时把条目写进 `$($acc)*` 后面即可(形状见 [`crate::catalog`] 的「域装配」一节)。
//! 现在没有条目,所以本宏是**空转移器**:只把累积表原样交给下一个域。
//! 本域在装配链里排在 `settings_java_entries` 之后、`settings_ai_entries` 之前,所以金表那几行
//! 也落在 `SettingsJavaReasonInstallRootTooLong` 与 `SettingsGroupAssistant` 之间。
//!
//! ## 只有一条 key 的理由
//!
//! 下载组的**行文案**(`并发数` / `单源尝试次数` / 「原值 9999 已按出厂 8 生效」这些)不在这里:
//! 它们由 presenter 按 schema 键现算(`dto::SettingRowView::label` / `description`),因为那些句子
//! 里带着**生效值**——把数字搬进静态目录只会再长出一份会说谎的文案。这一域只放「页面自己的
//! 按钮词」:提交文本框那一下的「应用」。
macro_rules! settings_download_entries {
($next:ident, $($rest:ident,)* { $($acc:tt)* }) => {
$next! { $($rest,)* { $($acc)* } }
$next! { $($rest,)* {
$($acc)*
// ── 文本行的提交按钮(`pages/settings/download.rs` 的 text 行)
SettingsDownloadsApply => ("Apply", "应用"),
} }
};
}