fix(app-iced): 说明只画一份(删滚动区重复)+ 口径三处改真

八审唯一阻断:中性说明画了两份(滚动区 546–557 与钉死区 576–587 像素级相同、重影)。
删掉滚动区那份,钉死区保留;01/02/05 与 900 的说明墨迹带现在只有一条(576–587 / 716–727)。

口径三处:
1. `section` 文档的滚动区内容改成实际(head + 六枚 chips + 错误行);
2. 旧的「≈150px / 无需滚动」改成八审实测(可见 96–104px、内容 76px、head 墨迹 462–501、
   chips 506–537 四角闭合);
3. 钉死区注释「标签与说明都搬到钉死区」改成事实:Shared 档的「安装选项」标签是**删掉**的
   (设计决定,八审裁决),只有说明是搬下去的;Pinned 档仍保留标签。
This commit is contained in:
AskaEth committed 2026-11-10 19:34:15 +08:00
1 parent e2e3c39f61
commit 33d05689e8
1 file changed
+12 -20
@@ -73,14 +73,15 @@ pub(super) fn version_menu_height(items: usize) -> f32 {
///
/// `scroll` = 面板此刻是不是「自己可滚」的那一档(`rows::TailShare::Shared`)。是的话:
///
/// - **滚动区**:head(版本 id + 安装按钮)+ 加载器 chips + 中性说明 + 错误行;
/// - **钉死区**:加载器版本菜单 + 实例名输入框。
/// - **滚动区**:head(版本 id + 安装按钮)+ 六枚加载器 chips + 错误行;
/// - **钉死区**:说明行(有说明时;否则是「加载器版本」标签)+ 版本菜单 + 实例名输入框。
///
/// 为什么菜单也要钉(D30 四审):裁切位置由**钉死区高度**决定,与窗宽无关(1180 与 720 都切在
/// 同一个 y)。之前只钉实例名,菜单就正好落在切线上——760 下菜单容器 642–706 只有 18px 可见、
/// 条目文字一格都没画出来。把菜单一起钉住之后,它不再依赖首屏剩余高度分配,可达性由结构保证;
/// 滚动区溢出时滚走的是**说明/错误行**(非控件);D30 六审把说明压成单行之后,
/// 1180×760 下滚动区 ≈150px,head + 标签 + 六枚 chip + 单行说明全在首屏、**无需滚动**。
/// 滚动区溢出时被滚走的是错误行(说明与菜单都在钉死区,不参与滚动)。
/// D30 八审实测:滚动区可见高 ≈96–104px,内容(head 40 + chips 32 + 间距 4)≈76px ⇒
/// 1180×760 下 head(墨迹 462–501)与六枚 chips(506–537,32px 四角闭合)完整在首屏。
pub(crate) fn section<'a>(
ui: &'a Ui,
catalog: Catalog,
@@ -165,26 +166,16 @@ pub(crate) fn section<'a>(
// 并排标签(方案 C)在这里不可行:六枚 chip 实测已占 404px,正文列只有 424px,
// 加上「安装选项」必然横向溢出、把第六枚裁掉——那是拿一个已完成项换另一个。
// 所以按塔授权的 B 落地:标签与说明都搬到钉死区(见下面的 `pinned`),滚动区只装控件。
// Shared 档**没有**「安装选项」标签:这是设计决定(D30 八审裁决)——六枚 chip 自解释,
// 且正文列只有 424px、六枚 chip 已占 404px,加标签必然横向裁掉最后一枚。
// 原版等 Pinned 档仍保留该标签(见上面 `!scroll` 那条路)。
let mut body = column![head, loader_row(ui, catalog, options)]
.spacing(ui.space(Space::X1))
.width(Length::Fill);
// 中性说明(M222):只解释这一页能装到哪一层,不套错误色、不影响确认键。
// 换行由 iced 的文本布局负责,长句不会横向溢出;但**视觉验收仍需截图确认**(D30)。
// 中性说明**只在钉死区画一份**(八审:这里原先也画了一份,两处像素级重影)。
// 「加载器版本」这一段只在**真该有列表**时出现:原版没有、静态不兼容没有(原因在下面那行)、
// 取不到也没有(同样在原因行)。留一个空标题只会让人以为界面缺了一块。
// 中性说明留在**滚动区**(D30 四审裁决):它两行高、且不是控件,溢出时被滚走可以接受;
// 加载器版本菜单是控件,已经搬到钉死区(见下面的 `pinned`),不再和它抢首屏高度。
if let Some(note) = &options.note {
body = body.push(frame::text_role(
ui,
TypeRole::BodySmall,
false,
note.as_str(),
ui.color(Role::OnSurfaceVariant),
));
}
if let Some(problem) = &options.problem {
body = body.push(frame::text_role(
ui,
@@ -198,8 +189,9 @@ pub(crate) fn section<'a>(
// 钉死区:加载器版本菜单 + 实例名(都不参与滚动)。见 `section` 的文档。
let mut pinned = column![].spacing(ui.space(Space::X2)).width(Length::Fill);
if show_versions(options) {
// 菜单上方那一行:**有中性说明就显示说明**(它讲的是「这一家的叠法」,
// 位置就在版本菜单正上方,语义对得上),没有说明时才退回通用标签。
// 菜单上方那一行:**有中性说明就显示说明**(它讲的是「这一家的叠法」,位置就在
// 版本菜单正上方,语义对得上);没有说明时才退回通用标签。
// 注意标签不是「搬」下来的:Shared 档的「安装选项」标签是**删掉**的(八审裁决,见上)。
// 高度相同(BodySmall 与 LabelMedium 都是一行),所以钉死区不涨。
let line = match &options.note {
Some(note) => frame::text_role(