fix(app-iced): 版本列表在三栏对半分档按整行取高(S1b/S9)

列表视口高度不再是「Fill 剩下的」:正文列高度由仓里已有的 `frame::body_height` 算出,
经 `view_sized` → `body` → `rails::three_column` → `rows::content` 传下来,Shared 档据此
`floor(((h − LIST_CHROME)/2) / ROW_PITCH) * ROW_PITCH` 取整行。

实测(1180×760):列表 245px → **239px**(分隔线 498 → 492,腾出的 6px 归面板),
`04` 对照**未变**(531 / 278px),720 窄窗**未变**(本来就是 4.0 整行、底缘 0 墨迹)。

两处修正写在提交里:
1. 第一版给所有三栏场合取整,把 `04` 也缩到 239px ⇒ 收窄为只在 `TailShare::Shared` 取整;
2. `rows.rs` 涨到 419 行撞 400 行门禁 ⇒ `TailShare` 与三个标定量纯搬移到 `rows/tail.rs`,
   `rows.rs` 回到 355 行(门禁 `components::gate` 与全仓扫描都绿)。

`view` 保留 4 参数(`#[cfg(test)]`,只有单测用),产品路径走 `view_sized`。
This commit is contained in:
AskaEth committed 2026-11-10 19:34:13 +08:00
1 parent f29ca609ec
commit 954281d71a
5 files changed
+131 -55

No files matched your search

+16 -52
View File
@@ -72,12 +72,15 @@ use crate::theme::Ui;
use super::super::frame;
use super::super::layout::rails::{LIST_DATE_WIDTH, LIST_KIND_WIDTH, ROW_GAP, ROW_ICON_BUTTON};
use super::super::layout::VersionRailTier;
use super::super::Message;
use super::install::{self, panel_state, PanelState};
use super::model::{Download, VersionRow};
use super::states;
mod tail;
pub(crate) use tail::{whole_rows, TailShare};
/// 列表列(三栏档与 chips 档共用一份)。
///
/// `share` 决定「列表」与「尾部面板」怎么分这块高度:三栏档钉死面板、chips 档各吃一半
@@ -87,6 +90,7 @@ pub(super) fn content<'a>(
catalog: Catalog,
model: &'a Download,
share: TailShare,
list_height: Option<f32>,
) -> Element<'a, Message> {
let visible = visible(model);
@@ -97,7 +101,14 @@ pub(super) fn content<'a>(
} else if visible.is_empty() {
states::empty(ui, catalog)
} else {
list(ui, catalog, model, &visible)
// 只有「列表与面板对半分」那一档才按整行取高:钉死档(面板矮)实测已经是整行
// (04 图 278px),取整反而会把它从 6 行缩到 5 行。
let height = if matches!(share, TailShare::Shared) {
list_height
} else {
None
};
list(ui, catalog, model, &visible, height)
};
// 列表与尾部面板之间**总是**有一条分隔线(三态一致):M123 的取证图里「选好了版本」
@@ -145,55 +156,6 @@ pub(super) fn content<'a>(
/// 「实例名那格滚得到」——harness 拿到这个 Id 就能派一次 `scroll_to` 再拍。
pub(crate) const PANEL_SCROLL_ID: &str = "download-panel";
/// 列表与尾部面板怎么分这块高度(M125 缺陷 1 的修法)。
///
/// | 档 | 分法 | 为什么 |
/// |---|---|---|
/// | `Wide` / `Narrow` / `Compact` | [`TailShare::Pinned`]:面板按内容高钉在底部,列表吃剩下的 | 竖栏档在 760 高的窗口里列表还剩 158px(3 整行),面板整块在屏内——两样都对 |
/// | `Chips` + 面板**占高度**(选项区展开 / 安装中) | [`TailShare::Shared`]:两半各 `Fill`,面板自己可滚 | chips 档比三栏档多花两行 chip(tabs 48 + chips 48 + 间距),列表只剩 **18px**(M123 实测 0.4 行),面板 316px 全在屏内也没用——版本号读不出来就换不了版本 |
/// | 任何档 + 只画 `Hint`(没选版本,面板只有一行) | [`TailShare::Pinned`] | 一行提示不值得对半分:700×760 下 main 是 **7 整行**在屏(不是 8——第 8 条墨迹其实是 `Pick a version, then install` 那句 hint,横向范围对不上版本号;要放 8 行得 352px,实测只剩 309~322px),对半分只剩 **4 整行**、下面留 160px 空白(r1 复审 P2-1,r2 修回 7) |
///
/// 判据是**档位**不是高度:页面的模型里只有 `window_width`(`pages/model.rs`),窗口高度
/// 没有接进页面(要接得改 `pages/mod.rs` 的入口签名,超出本页的边界)。所以这里按「哪一档
/// 的竖排 chrome 会把列表压没」来分,并在报告里登记这条判据的边界。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum TailShare {
/// 面板钉在底部(三栏档)。
Pinned,
/// 面板与列表各吃一半(chips 档)。
Shared,
}
impl TailShare {
/// 档位 + **面板形态** → 分高方式(纯函数,单测直接钉它)。
///
/// 两个条件必须同时成立才共享:
/// 1. 档位是 `Chips`(多花两行 chip,竖排预算最紧的那一档);
/// 2. 面板真的**占高度**——`Options`(选中了版本、选项区展开)或 `Install`(进度 / 失败)。
///
/// `Hint`(刚进页面还没选版本)只是**一行**提示(≈30px),对半分会让列表从 **7 整行**
/// 掉到 **4 整行**、下半块留 ≈160px 空画布(r1 复审 P2-1 实测:main 在 700×760 的
/// `Hint` 态是 7 整行——不是 8,第 8 条墨迹其实是 `Pick a version, then install` 那句
/// hint,横向范围对不上版本号;r2 修回 7 整行)。所以 `Hint` **在任何档位都钉死**。
pub(super) fn of(tier: VersionRailTier, state: &PanelState<'_>) -> Self {
match (tier, state) {
(VersionRailTier::Chips, PanelState::Options(_) | PanelState::Install(_)) => {
Self::Shared
}
// M222 D30 r1 S1 / r2 S7:**带加载器版本列表**的选项区在任何档位都太高。
// 三栏档(1180×760)实测:修前面板 204→372px,版本列表 6.0 行(278px)被压到
// 2.4 行(110px,底缘切在第三行图标上);改成 Shared 之后版本列表 **245px = 5.29 行**、
// 面板 237px(分隔线 y=498)。面板因此变矮,实例名会被挤出首屏 ⇒ 同一轮把它
// **钉成面板页脚**(`install::panel_with` 的 `shared` 分支 + `options::section`)。
// 仍欠一项:245px 不是行高整数倍,列表底缘仍切在第 6 行中间(S1b/S9)。
// 修它要把「分给列表的高度」从 `pages/download.rs` 传进来做 floor 取整
// (`responsive` 在 Fill 子项上拿不到确定高度,实测无效,已回退)。
(_, PanelState::Options(options)) if options.has_loader_versions() => Self::Shared,
_ => Self::Pinned,
}
}
}
/// 搜索条 + 清空按钮 + 命中数(三者一行;命中数只在有查询词时出现)。
pub(super) fn search_row<'a>(
ui: &'a Ui,
@@ -288,6 +250,7 @@ fn list<'a>(
catalog: Catalog,
model: &'a Download,
visible: &[&'a VersionRow],
height: Option<f32>,
) -> Element<'a, Message> {
let entries = column(
visible
@@ -306,7 +269,8 @@ fn list<'a>(
.scroller_width(frame::SCROLLBAR_WIDTH)
.margin(frame::SCROLLBAR_MARGIN),
))
.height(Length::Fill)
// `Some` = 三栏档按**整行**取高(见 `tail::whole_rows`);`None` = chips 档照旧 Fill。
.height(height.map_or(Length::Fill, Length::Fixed))
.style(frame::scroll_style(ui))
.into()
}