feat(app-iced): M107 DLVRAIL —— 版本管理页三栏侧栏 + 跨类型搜索
用户令(信息架构):这一页从「下载」改称「版本管理」,版面从「一排 tab + 平铺列表」 改成**页面内三栏**:版本类型栏 + 主版本栏 + 列表/详情,并加搜索框。 - **三栏几何**(`pages/layout/rails.rs`,纯函数 + 数值表):类型栏 140/64、主版本栏 140/64、 间距 24、列表列下限 424(行宽红线)。四档由**可用宽**裁决:Wide ≥888 / Narrow ≥676 / Compact ≥600 / Chips <600,三个门槛都是 `栏宽 + 间距 + 424` 算出来的,不是拍的 - **主版本分组规则**(`download/group.rs`):正式版/预发布按 `major.minor`(`1.21.9-pre3` → `1.21`)、 周更按年桶(`24w14a` → `24w`)、远古版**没有主版本**(`rd-132211`/`a1.2.6` → 第二级只有「全部」); 判据用真实版本样本钉住,不按「第一个点」切 - **跨类型搜索**(`search_bar` + 清空 + 命中数):查询词写进 `AppState.download_query`(页面无状态, 只能这么活),`hits` 是**跨分类**读数;三条口径分开:「有命中」/「没有匹配」/「命中在别的类型里」 - 两级侧栏都用 `navigation::list_item` / `tabs` / `chip` / `buttons::icon`:Tab 可达、hover/pressed/ 选中态全部来自组件,页面不自己写状态层 - 右栏展开(M104 `content_width` 852)⇒ 可用宽 716 ⇒ Narrow 档,列表 464(任务书那句 492 漏扣 96px 的页边距与栏间距,报告里给了完整数值表) - 文案 11 条中英进 `crates/i18n`(新域宏接在装配链末尾 ⇒ `Key::ALL` 只追加,金表只追加) - 护栏:两层侧栏都存在 + 列表按第二级选中态过滤(变异可证)、三档门槛、424 下限扫描、 版本行单行宽账、搜索条真的装着 - `install.rs` 只动了「已装」分支(加一句「已安装」解释禁用按钮),没碰 M105 的选项区 取证:`DevDocs/artifacts/m107/`(10 张:三档 × 浅深 + 搜索命中 + 空 + 异地 + 远古版)
This commit is contained in:
1 parent
72b0c9d465
commit
89a51a63b1
24 files changed
+2000
-340
No files matched your search
@@ -83,6 +83,21 @@ impl App {
|
||||
self.dispatch(AppCommand::ListVersions(kind));
|
||||
}
|
||||
}
|
||||
// M107:查询词落在快照里(无状态视图的唯一存活方式),再走同一条重建路径过滤。
|
||||
pages::Message::SetVersionQuery(query) => {
|
||||
self.rebuild_after_query(query.clone());
|
||||
}
|
||||
pages::Message::ClearVersionQuery => {
|
||||
self.rebuild_after_query(String::new());
|
||||
}
|
||||
// M107:主版本桶的选中是纯视图态,不重建、不派命令(同 `SelectVersion`)。
|
||||
pages::Message::SelectMajor(key) => {
|
||||
self.view.download.selected_major = key.clone();
|
||||
}
|
||||
// M107:类型栏的手动折叠也是纯视图态。
|
||||
pages::Message::ToggleTypeRail => {
|
||||
self.view.download.type_rail_folded = !self.view.download.type_rail_folded;
|
||||
}
|
||||
pages::Message::Action(pages::Action::RefreshSources) => {
|
||||
match self.view.download.category.command() {
|
||||
Some(kind) => self.dispatch(AppCommand::ListVersions(kind)),
|
||||
@@ -151,4 +166,28 @@ impl App {
|
||||
mc_version: version,
|
||||
});
|
||||
}
|
||||
|
||||
/// 搜索词变了:写进快照 → 重建视图 → **把纯视图态捡回来**。
|
||||
///
|
||||
/// `refresh_view()` 整块换掉 `self.view`,而它只把 `category` 与**安装草稿**带回去(`app/state.rs`
|
||||
/// 归 M105/M106)。所以「折叠状态」与「选中的主版本桶」必须在重建前后自己搬一次——否则用户敲第一个
|
||||
/// 字符,展开着的类型栏就自己收起来、选中的主版本也跳回「全部」。
|
||||
/// 「搜索时侧栏保留当前位置」这条要求,落点就是这里的四行。
|
||||
fn rebuild_after_query(&mut self, query: String) {
|
||||
self.state.download_query = query;
|
||||
let major = self.view.download.selected_major.take();
|
||||
let folded = self.view.download.type_rail_folded;
|
||||
self.view_dirty = true;
|
||||
self.refresh_view();
|
||||
// 回填要**校验**:桶是按当前行聚合法出来的,新桶列表里没有的那个选择不该被复活
|
||||
// (复审 P2-1(a):否则会出现「侧栏没有任何一项点亮」的幽灵选中)。
|
||||
self.view.download.selected_major = major.filter(|key| {
|
||||
self.view
|
||||
.download
|
||||
.buckets
|
||||
.iter()
|
||||
.any(|bucket| bucket.key.as_deref() == Some(key.as_str()))
|
||||
});
|
||||
self.view.download.type_rail_folded = folded;
|
||||
}
|
||||
}
|
||||
@@ -63,10 +63,16 @@ impl App {
|
||||
pages::Message::SelectVersion(_)
|
||||
| pages::Message::InstallVersion(_)
|
||||
| pages::Message::CancelInstall
|
||||
// M105 的三支 + M107 的四支 + 分类:全部由 `on_download` 提前消化(显式列出保住穷尽性)
|
||||
| pages::Message::SetLoader(_)
|
||||
| pages::Message::SetLoaderVersion(_)
|
||||
| pages::Message::SetInstanceName(_)
|
||||
| pages::Message::SetCategory(_) => debug_assert!(false, "应由 on_download 消费"),
|
||||
| pages::Message::SetCategory(_)
|
||||
// M107 的四支同属下载页(查询 / 清空 / 主版本桶 / 折叠类型栏)
|
||||
| pages::Message::SetVersionQuery(_)
|
||||
| pages::Message::ClearVersionQuery
|
||||
| pages::Message::SelectMajor(_)
|
||||
| pages::Message::ToggleTypeRail => debug_assert!(false, "应由 on_download 消费"),
|
||||
// M95:清空日志是**呈现层**操作(`log_lines` 是 presenter 的公开快照字段,
|
||||
// 不派业务命令、不写持久状态)
|
||||
pages::Message::Action(pages::Action::ClearLogs) => {
|
||||
|
||||
Reference in new issue
Block a user