fix(app-iced): M125 chips 档列表不被选项区压成缝;Compact 档主版本首项不再裁字
两条缺陷都是 M123 取证时在真图上拍出来的,塔台另行核过图: 缺陷 1(medium):chips 档(窗口 < 736,可用宽 < 600)里选项区按内容高 ≈316px 钉在列表下面,列表只剩 18px(0.4 行,行高 44)——版本号读不出来、 换不了版本。修法:`rows::TailShare` 两档,chips 档改成「列表与面板各吃一半、 面板自己可滚」(列表拿到 ≈182px = 4 整行,面板顶端那个实心「安装」与五个 loader chip 仍在屏内);三栏三档照旧钉死(760 高下列表还有 3 整行、面板 整块在屏内,两样都对)。判据按档位而不是按高度:页面模型里只有 window_width, 窗口高度没接进页面(边界写进 TailShare 文档与报告)。 缺陷 2(medium):Compact 档主版本栏宽 64,`ListItem` 两侧内边距各 16 ⇒ 文本格 32,首项「All versions」要 ≈84 ⇒ 图上只剩「All v」;中文「全部版本」= 4 全角字 = 64,32 里只剩「全部」且正好顶到裁切边。修法:图标条档的「全部版本」不画文字, 改画与本页第一级那个「全部」同一个网格图标(40×40 Tonal 药丸 + 全称 tooltip); 桶标签(1.21/24w,实测墨迹 26)放得下,照旧画原文。`rails.rs` 那条「64 宽里 1.21 仍完整」的注释改成实测宽度表,并写清它对首项不成立。 顺带:列表与尾部面板之间补上分隔线(三态一致),`rows::content` 与两个装配点 按档位传 `TailShare`。 守门: - `tests/options_shot.rs` 解掉 M123 那条 `#[ignore]`(期望值一个字没改,只加 「列表区 ≥ 3 整行」与「面板仍在屏内、没被底边切」两条); - 新增 `a_compact_tier_shot_draws_an_icon_for_the_first_major_entry`:缺陷 2 的 像素守门(首项是 40×40 居中药丸,不是 64×44 通栏文字行)。复审建议的 「墨迹右边界 ≤ 栏右内边界」在坏图上也是绿的(修前墨迹 216..244,边界 248), 所以改钉形状,理由写在测试文档里; - `tests/rails.rs`:中文与英文都走 Icon 分支、以及 32px 文本格的宽度账 (「全部版本」= 64 > 32 是精确值,「全部」= 32 零余量所以不选短标签); - `tests/view.rs`:档位 → TailShare 的决策面 + 两个装配点都按档位传。 未改产品文案、未改窗口最小宽、未动 M123 的任何断言期望值。
This commit is contained in:
1 parent
df0e98d811
commit
822f98022d
7 files changed
+444
-47
No files matched your search
@@ -79,9 +79,14 @@ pub(super) fn three_column<'a>(
|
||||
rails.major_rail,
|
||||
major_rail(ui, catalog, model, rails.major_rail)
|
||||
),
|
||||
container(rows::content(ui, catalog, model))
|
||||
.width(Length::Fixed(rails.list))
|
||||
.height(Length::Fill),
|
||||
container(rows::content(
|
||||
ui,
|
||||
catalog,
|
||||
model,
|
||||
rows::TailShare::of(rails.tier),
|
||||
))
|
||||
.width(Length::Fixed(rails.list))
|
||||
.height(Length::Fill),
|
||||
]
|
||||
.spacing(super::super::layout::rails::RAIL_GAP)
|
||||
.width(Length::Fill)
|
||||
@@ -165,19 +170,21 @@ fn labeled<'a>(
|
||||
press: Message,
|
||||
) -> Element<'a, Message> {
|
||||
let button = buttons::icon(ui, select_variant(selected), kind, Some(press), None);
|
||||
tooltip(
|
||||
button,
|
||||
container(frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodySmall,
|
||||
false,
|
||||
label,
|
||||
ui.color(Role::OnSurface),
|
||||
))
|
||||
.padding(ui.space(Space::X2))
|
||||
.style(move |_theme| frame::filled(ui.layer(MaterialLayer::Overlay))),
|
||||
Position::Right,
|
||||
)
|
||||
tooltip(button, tip_body(ui, label), Position::Right).into()
|
||||
}
|
||||
|
||||
/// tooltip 的正文盒子(`BodySmall` + `OnSurface` 叠 `Overlay` 层):类型栏的图标项与
|
||||
/// 主版本栏图标条档的「全部版本」共用一份文字语言。
|
||||
fn tip_body<'a>(ui: &'a Ui, label: &'a str) -> Element<'a, Message> {
|
||||
container(frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodySmall,
|
||||
false,
|
||||
label,
|
||||
ui.color(Role::OnSurface),
|
||||
))
|
||||
.padding(ui.space(Space::X2))
|
||||
.style(move |_theme| frame::filled(ui.layer(MaterialLayer::Overlay)))
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -255,7 +262,7 @@ fn major_rail<'a>(
|
||||
}
|
||||
|
||||
for entry in major_entries(catalog, model) {
|
||||
body = body.push(major_item(ui, entry.label, entry.key, entry.selected));
|
||||
body = body.push(major_item(ui, entry, icon_only));
|
||||
}
|
||||
|
||||
body.into()
|
||||
@@ -276,6 +283,43 @@ pub(super) struct MajorEntry<'a> {
|
||||
pub selected: bool,
|
||||
}
|
||||
|
||||
/// 一项在 iced 里**画成什么样**(纯函数产出,单测直接钉它 —— 两种形状的取舍见 [`major_shape`])。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(super) enum MajorShape<'a> {
|
||||
/// `ListItem` 单行文字(展开档的每一项、图标条档的桶标签)
|
||||
Text(&'a str),
|
||||
/// 图标 + tooltip 全称(图标条档的「全部版本」,见 [`major_shape`] 的宽度账)
|
||||
Icon(&'a str),
|
||||
}
|
||||
|
||||
/// 图标条档画成什么样:**只有「全部版本」这一项不是文字**。
|
||||
///
|
||||
/// ## 64 宽的可见文本宽是 **32**,不是 40(M123 取证实测)
|
||||
///
|
||||
/// `ListItem` 两侧内边距各 16(`pad_start` / `pad_end`),所以 64 宽的栏里文本格
|
||||
/// = 64 − 32 = **32**,再长就被 `clip(true)` 切掉。`BodyLarge` 16px 下:
|
||||
///
|
||||
/// | 标签 | 墨迹宽 | 32 里放得下? |
|
||||
/// |---|---|---|
|
||||
/// | `1.21` | 26(736×760 那张实测) | ✓ 余量 6 |
|
||||
/// | `24w` | 26(同上) | ✓ 余量 6 |
|
||||
/// | `All versions` | ≈84(12 字符,按 0.4em 下限也有 77) | ✗ 只画得出「All v」(缺陷 2 的原图) |
|
||||
/// | `全部版本` | 4 × 16 = **64**(全角 1em,精确值) | ✗ 只画得出「全部」,而且正好顶到裁切边 |
|
||||
///
|
||||
/// 短标签这条退路也不行:中文「全部」= 2 × 16 = **32**,与文本格**一样宽、零余量**,
|
||||
/// 「裁不裁」取决于字体渲染的小数位——一个查不出、也守不住的边界。所以图标条档的
|
||||
/// 「全部版本」**不画文字**:换成与本页第一级那个「全部」同一个网格图标
|
||||
/// ([`category_icon`] 的 `Category::All`),全称进 tooltip(宽度不设限,中英文都完整)。
|
||||
///
|
||||
/// 桶标签本来就是 3~5 字符的短串,两档都照旧画原文。
|
||||
pub(super) const fn major_shape(entry: MajorEntry<'_>, icon_only: bool) -> MajorShape<'_> {
|
||||
if icon_only && entry.key.is_none() {
|
||||
MajorShape::Icon(entry.label)
|
||||
} else {
|
||||
MajorShape::Text(entry.label)
|
||||
}
|
||||
}
|
||||
|
||||
/// 第二级侧栏要画的全部项:`[全部版本, 1.21, 1.20, …]`,顺序 = 桶的版本序。
|
||||
///
|
||||
/// 抽成纯函数是为了让「最后一个桶可点」这件事**可断言**(复审 P2-2 的要求):
|
||||
@@ -303,18 +347,38 @@ pub(super) fn major_entries<'a>(catalog: Catalog, model: &'a Download) -> Vec<Ma
|
||||
entries
|
||||
}
|
||||
|
||||
/// 主版本的一项:`ListItem` 单行(64 宽里 `1.21` 仍完整——`BodyLarge` 4 字符 ≈ 32px ≤ 64−32 内边距)。
|
||||
/// 主版本的一项:形状由 [`major_shape`] 决定(图标条档的「全部版本」是图标 + tooltip,
|
||||
/// 其余都是 `ListItem` 单行文字)。
|
||||
fn major_item<'a>(
|
||||
ui: &'a Ui,
|
||||
label: &'a str,
|
||||
key: Option<&str>,
|
||||
selected: bool,
|
||||
entry: MajorEntry<'a>,
|
||||
icon_only: bool,
|
||||
) -> Element<'a, Message> {
|
||||
let mut item = ListItem::new(label, Message::SelectMajor(key.map(str::to_string)));
|
||||
if selected {
|
||||
item = item.selected();
|
||||
let press = Message::SelectMajor(entry.key.map(str::to_string));
|
||||
|
||||
match major_shape(entry, icon_only) {
|
||||
MajorShape::Text(label) => {
|
||||
let mut item = ListItem::new(label, press);
|
||||
if entry.selected {
|
||||
item = item.selected();
|
||||
}
|
||||
list_item(ui, item)
|
||||
}
|
||||
// 图标条档的「全部版本」:图标(与本页第一级的「全部」同一个网格)+ 全称 tooltip。
|
||||
// 高度对齐 `ListItem` 的行高,两档的行节奏才一样。
|
||||
MajorShape::Icon(full) => container(labeled(
|
||||
ui,
|
||||
full,
|
||||
category_icon(Category::All),
|
||||
entry.selected,
|
||||
press,
|
||||
))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fixed(ui.metrics().row_height))
|
||||
.align_x(Alignment::Center)
|
||||
.align_y(Alignment::Center)
|
||||
.into(),
|
||||
}
|
||||
list_item(ui, item)
|
||||
}
|
||||
|
||||
/// 顶部 chips(可用宽 < 600 时三栏不成立:类型退回 Primary tabs,主版本变成 Secondary chips 行)。
|
||||
|
||||
Reference in new issue
Block a user