fix(download): 窄档面板加专属预算,首屏露出 head+六枚 chip+说明、实例名回到 56px(M227)

720×760(chips 档)原先走 `TailShare::Shared`:面板与列表各吃 Fill 的一半,面板钉死区
(说明 + 菜单 + 实例名 ≈180px)把它吃穿 ⇒ 滚动区视口 0,head(版本 id + 安装按钮)、
六枚加载器 chip、说明一个像素都不在屏,实例名被挤成 35px 且降部被自身边框裁掉
(M222 D30 五审 `artifacts/m222/visual-verdict-r5-hold.md`)。

改法(把 M222 在 1180 档验证过的「面板先保预算、列表吃整行」落到窄档):

- `TailShare` 拆出第三支 `Narrow`(chips 档 + 面板占高度),`of()` 的三条 arm 与
  `Shared` 的机制注释按 r8 finding 重写(旧文档只写 M125 那一条条件);
- 新增 `CHIPS_STACK` 121 / `CHIPS_LIST_CHROME` 119 / `CHIPS_PANEL_BUDGET` 192 与
  `narrow_rows()`:720/760 下面板先拿预算,列表 = **132px = 3 整行**(M125 像素守门的下限);
- `options::section` 三分支:窄档钉死区**只留实例名**,head / 六枚 chip / 说明 / 版本菜单
  进滚动区(滚动区 120px ≥ 首屏 104,菜单露容器上沿 + 滚动条可见);
- `TailShare::list_height()` 把「列表吃多少」收到一处,两个装配点共用(三栏档行为不变)。

取舍:窄档列表 4 整行 → 3 整行;菜单从钉死改为可滚。理由(459px 里「钉住菜单」+「3 整行
列表」互斥)写在 `rows/tail.rs::CHIPS_PANEL_BUDGET`。

实测(tiny-skia 出图 + 自写 measure.py,DevDocs/artifacts/m227/):
720×760 分隔线 559→514、滚动区 0→120、head 539–578、chips 583–614(32px)、说明 623–634
(8.98:1 浅 / 10.83:1 深)、实例名 668–723 = 56px(inset 12/9/17);
700×760(options-fabric)实例名从「完全不在屏」回到 56px;四条像素守门全绿;
1180×760 浅/深/中 与 1180×900 **逐像素零变化**。
This commit is contained in:
AskaEth committed 2026-11-10 23:07:19 +08:00
1 parent 6c060a09e2
commit a70d5f8010
9 files changed
+331 -159

No files matched your search

+21 -18
View File
@@ -29,11 +29,14 @@
//! 都在面板钉死区,见 `options/view.rs::section`)。
//! 同样的 760 高窗口里:三栏档列表还剩 158px(3 整行),chips 档只剩 18px。
//!
//! 修法是 [`TailShare`] 两档:**不带加载器版本列表**的选项区在三栏档照旧钉死(面板整块在屏内),
//! 修法是 [`TailShare`] 三档:**不带加载器版本列表**的选项区在三栏档照旧钉死(面板整块在屏内),
//! chips 档**且面板真的占高度**
//! (选项区展开 / 安装中)时改成「**面板先保预算、剩下按整行给列表**」
//! (`tail::whole_rows` + `PANEL_BUDGET = 300`):1180×760 下列表 **176px = 4 整行**,
//! 面板拿走其余(≈307px)。实例名那格**已经钉死**在面板底部、不需要滚(M222 `6f87c8b`)。
//! (`tail::narrow_rows` + `CHIPS_PANEL_BUDGET = 192`):700/720×760 下列表 **132px = 3 整行**、
//! 面板拿走其余(208px)。M227 之前这一档是「Fill 与 Fill 五五分」——面板只分到 164px,
//! 钉死区(说明 + 菜单 + 实例名 ≈180px)把它吃穿,滚动区剩 0、head / 六枚 chip 全不在屏。
//! 三栏档 + 带版本列表的选项区走另一支(`tail::whole_rows` + `PANEL_BUDGET = 300`):
//! 1180×760 列表 **176px = 4 整行**、面板 ≈294px,那里菜单与说明都钉在面板底部。
//! 「刚进页面还没选版本」(`Hint`,面板只有一行提示)**不共享**:那一态 main 本来就有
//! **7 整行**在屏(不是 8:第 8 条墨迹其实是 `Pick a version, then install` 那句 hint,
//! 横向范围对不上版本号;700×760 上放 8 行要 352px,实测只剩 309~322px),五五分会砍成
@@ -82,13 +85,14 @@ use super::states;
mod tail;
pub(crate) use tail::{whole_rows, TailShare};
pub(crate) use tail::TailShare;
/// 列表列(三栏档与 chips 档共用一份)。
///
/// `share` 决定「列表」与「尾部面板」怎么分这块高度(真实分支见 `tail::TailShare::of`):
/// `Pinned` = 面板按内容高钉在底部、列表吃剩下的;`Shared` = 面板先吃 `tail::PANEL_BUDGET`、
/// 列表按**整行**吃剩下的(`tail::whole_rows`)。哪些组合走哪一支由那一处决定,这里不重复判。
/// `Pinned` = 面板按内容高钉在底部、列表吃剩下的;`Shared` / `Narrow` = 面板先吃预算、
/// 列表按**整行**吃剩下的(`tail::whole_rows` / `tail::narrow_rows`,两者差别在面板内部
/// 钉什么,见 `tail::CHIPS_PANEL_BUDGET`)。哪些组合走哪一支由那一处决定,这里不重复判。
pub(super) fn content<'a>(
ui: &'a Ui,
catalog: Catalog,
@@ -105,40 +109,38 @@ pub(super) fn content<'a>(
} else if visible.is_empty() {
states::empty(ui, catalog)
} else {
// 只有 `Shared`(面板先保预算)那一档才按整行取高:`Pinned` 档(面板矮)实测已经
// 是整行(`04` 图),取整反而会把它从 6 行缩到 5 行。
let height = if matches!(share, TailShare::Shared) {
list_height
} else {
// 只有「面板先保预算」那两支(`Shared` / `Narrow`)才按整行取高:`Pinned` 档(面板矮)
// 实测已经是整行(`04` 图),取整反而会把它从 6 行缩到 5 行。
let height = if matches!(share, TailShare::Pinned) {
None
} else {
list_height
};
list(ui, catalog, model, &visible, height)
};
// 列表与尾部面板之间**总是**有一条分隔线(三态一致):M123 的取证图里「选好了版本」
// 那一态原先没有它,版本行与选项区第一行(版本号 + 安装按钮)读起来像同一块内容。
let shared = matches!(share, TailShare::Shared);
let tail: Element<'a, Message> = column![
divider::full(ui),
install::panel_with(ui, catalog, model, shared)
install::panel_with(ui, catalog, model, share)
]
.spacing(ui.space(Space::X3))
.width(Length::Fill)
.into();
// chips 档 / 带版本列表的选项区:面板收回自己的一半。
// chips 档 / 带版本列表的选项区:面板吃满自己那份。
//
// `PanelState::Options` 走**面板内部**的滚动(上半块可滚 + 实例名钉页脚,见 `install::panel`),
// 所以这里不再整块套一层 scrollable——那一层曾让窄窗出现两条并列滚动条,也因为把实例名
// 卷进滚动区而让它掉到首屏外(D30 r2 S7)。其它面板(安装中/失败)内容短,保留外层滚动。
let tail: Element<'a, Message> = match (share, panel_state(model)) {
(TailShare::Shared, PanelState::Options(_)) => tail,
(TailShare::Shared, _) => scrollable(tail)
(TailShare::Pinned, _) | (_, PanelState::Options(_)) => tail,
(TailShare::Shared | TailShare::Narrow, _) => scrollable(tail)
.id(iced::widget::Id::new(PANEL_SCROLL_ID))
.height(Length::Fill)
.style(frame::scroll_style(ui))
.into(),
(TailShare::Pinned, _) => tail,
};
column![
@@ -273,7 +275,8 @@ fn list<'a>(
.scroller_width(frame::SCROLLBAR_WIDTH)
.margin(frame::SCROLLBAR_MARGIN),
))
// `Some` = 三栏档的 `Shared` 分支按**整行**取高(见 `tail::whole_rows`);`None` = 其它(含 chips 档)用 Fill。
// `Some` = 面板先保预算那一档按**整行**取高(三栏档 `tail::whole_rows` /
// chips 档 `tail::narrow_rows`);`None` = `Pinned`(面板矮)用 Fill。
.height(height.map_or(Length::Fill, Length::Fixed))
.style(frame::scroll_style(ui))
.into()