diff --git a/crates/app-iced/src/pages/download/options/view.rs b/crates/app-iced/src/pages/download/options/view.rs index 5d8ec8b..ed13569 100644 --- a/crates/app-iced/src/pages/download/options/view.rs +++ b/crates/app-iced/src/pages/download/options/view.rs @@ -98,19 +98,73 @@ pub(crate) fn section<'a>( .width(Length::Fill) .align_y(Alignment::Center); - let mut body = column![ - head, - frame::text_role( + // 钉死档(原版 / 没有加载器版本列表)**保持旧结构**:标签与说明都在列内。 + // 为什么不一并改:`04` 是别处基线图的对照,它的面板矮、列表 6 行——把标签撤出会 + // 让面板矮 26px,列表涨到 302px(6.86 行)反而切出半行。方案 B 只对 Shared 档生效。 + if !scroll { + let mut plain = column![ + head, + frame::text_role( + ui, + TypeRole::LabelMedium, + false, + catalog.text(Key::DownloadOptionsTitle), + ui.color(Role::OnSurfaceVariant), + ), + loader_row(ui, catalog, options), + ] + .spacing(ui.space(Space::X2)) + .width(Length::Fill); + if let Some(note) = &options.note { + plain = plain.push(frame::text_role( + ui, + TypeRole::BodySmall, + false, + note.as_str(), + ui.color(Role::OnSurfaceVariant), + )); + } + if show_versions(options) { + plain = plain.push(frame::text_role( + ui, + TypeRole::LabelMedium, + false, + catalog.text(Key::DownloadOptionsLoaderVersion), + ui.color(Role::OnSurfaceVariant), + )); + plain = plain.push(version_list(ui, catalog, options)); + } + if let Some(problem) = &options.problem { + plain = plain.push(frame::text_role( + ui, + TypeRole::BodySmall, + false, + problem.as_str(), + ui.color(Role::Error), + )); + } + plain = plain.push(text_field( ui, - TypeRole::LabelMedium, - false, - catalog.text(Key::DownloadOptionsTitle), - ui.color(Role::OnSurfaceVariant), - ), - loader_row(ui, catalog, options), - ] - .spacing(ui.space(Space::X2)) - .width(Length::Fill); + Field::new(options.instance_name.as_str()) + .variant(FieldVariant::Outlined) + .label(catalog.text(Key::DownloadOptionsInstanceName)) + .placeholder(catalog.text(Key::DownloadOptionsInstanceNameHint)), + Message::SetInstanceName, + )); + return plain.into(); + } + + // 滚动区只剩 head + 六枚 chips(方案 B,D30 六审裁决)。 + // + // 为什么把「安装选项」标签与中性说明都撤出滚动区: + // 五审 82px → 六审 103px 的视口里,head(40) + 标签(17) + chips(32) + 两处间距(16) = 105px, + // 差 2px 就把 chip 的底边框裁掉;再塞说明(20px)就差 27~29px,说明整块 0 像素。 + // 并排标签(方案 C)在这里不可行:六枚 chip 实测已占 404px,正文列只有 424px, + // 加上「安装选项」必然横向溢出、把第六枚裁掉——那是拿一个已完成项换另一个。 + // 所以按塔授权的 B 落地:标签与说明都搬到钉死区(见下面的 `pinned`),滚动区只装控件。 + let mut body = column![head, loader_row(ui, catalog, options)] + .spacing(ui.space(Space::X1)) + .width(Length::Fill); // 中性说明(M222):只解释这一页能装到哪一层,不套错误色、不影响确认键。 // 换行由 iced 的文本布局负责,长句不会横向溢出;但**视觉验收仍需截图确认**(D30)。 @@ -141,13 +195,26 @@ pub(crate) fn section<'a>( // 钉死区:加载器版本菜单 + 实例名(都不参与滚动)。见 `section` 的文档。 let mut pinned = column![].spacing(ui.space(Space::X2)).width(Length::Fill); if show_versions(options) { - pinned = pinned.push(frame::text_role( - ui, - TypeRole::LabelMedium, - false, - catalog.text(Key::DownloadOptionsLoaderVersion), - ui.color(Role::OnSurfaceVariant), - )); + // 菜单上方那一行:**有中性说明就显示说明**(它讲的是「这一家的叠法」, + // 位置就在版本菜单正上方,语义对得上),没有说明时才退回通用标签。 + // 高度相同(BodySmall 与 LabelMedium 都是一行),所以钉死区不涨。 + let line = match &options.note { + Some(note) => frame::text_role( + ui, + TypeRole::BodySmall, + false, + note.as_str(), + ui.color(Role::OnSurfaceVariant), + ), + None => frame::text_role( + ui, + TypeRole::LabelMedium, + false, + catalog.text(Key::DownloadOptionsLoaderVersion), + ui.color(Role::OnSurfaceVariant), + ), + }; + pinned = pinned.push(line); pinned = pinned.push(version_list(ui, catalog, options)); } pinned = pinned.push(text_field( @@ -159,11 +226,6 @@ pub(crate) fn section<'a>( Message::SetInstanceName, )); - if !scroll { - // 钉死档(三栏 + 无版本列表 / chips 以外的矮面板):行为与以前一致,一列内容到底。 - body = body.push(Element::from(pinned)); - return body.into(); - } column![ scrollable(body) .height(Length::Fill)