fix(app-iced,i18n): 分高改「面板先保预算」+ 说明压成单行(D30 五审一次性重分配)

五审:菜单文字/720 列表/44-97 标定/04 都过,但滚动区被压到 82px(宽)/24px(窄)——宽档切
「安装选项」字身、六枚 chip 0 像素。塔裁决停止逐轮调顺序,一次性重分配:

1. **分高从「对半分」改成「面板先保预算」**:`PANEL_BUDGET = 300`(滚动区 128 + 钉死区 136),
   `whole_rows = floor((column − LIST_CHROME − PANEL_BUDGET)/44) × 44`。
   1180×760:580−97−300 = 183 ⇒ **176px = 4 整行**(原 5 行),面板 307px ⇒ 滚动区 ≈150px;
   1180×900:323 ⇒ **308px = 7 整行**(未变)。720 档走 `None`(Fill),未动。
2. **说明压成单行**(`DownloadOptionsLiteLoaderVanillaOnly`):两行 28px 是滚动区最大的可压项。
   en `Vanilla parent only — Forge goes through the CLI` / zh `只叠原版;叠 Forge 请走命令行`;
   完整命令行说法留在 `ull help install`。单测断言随之改成「含该句 + 只有一行」并写明原因。

文档按六审要求改口:滚走的是说明/错误行(非控件);说明变单行后 760 档滚动区已能装下
head+标签+chips+单行说明,**无需滚动**。
This commit is contained in:
AskaEth committed 2026-11-10 19:34:14 +08:00
1 parent 6eb7132ab0
commit cb2cffb3ca
5 files changed
+25 -12

No files matched your search

@@ -291,11 +291,10 @@ fn liteloader_carries_a_neutral_note_without_blocking_confirm() {
Lang::En.catalog(),
);
let note = options.note.as_deref().expect("LiteLoader 应带中性说明");
assert!(note.contains("vanilla"), "{note}");
assert!(
note.contains("--loader liteloader"),
"要给出可执行的下一步:{note}"
);
// 文案在 D30 五审后压成**单行**(两行 28px 是滚动区最大的可压项),断言随之改为
// 「说清只支持原版父链、且确实只有一行」;完整命令行说法在 `ull help install` 里。
assert!(note.contains("Vanilla parent only"), "{note}");
assert_eq!(note.lines().count(), 1, "必须是一行:{note}");
assert!(options.problem.is_none(), "中性说明不能变成错误");
assert!(options.can_confirm, "说明不该禁用确认键");
@@ -312,7 +311,7 @@ fn liteloader_carries_a_neutral_note_without_blocking_confirm() {
Lang::ZhCn.catalog(),
);
let note = options.note.as_deref().expect("中文也要有说明");
assert!(note.contains("原版"), "{note}");
assert!(note.contains("只叠原版"), "{note}");
assert!(options.can_confirm);
// 别家加载器不带这条说明。
@@ -76,7 +76,8 @@ pub(super) fn version_menu_height(items: usize) -> f32 {
/// 为什么菜单也要钉(D30 四审):裁切位置由**钉死区高度**决定,与窗宽无关(1180 与 720 都切在
/// 同一个 y)。之前只钉实例名,菜单就正好落在切线上——760 下菜单容器 642–706 只有 18px 可见、
/// 条目文字一格都没画出来。把菜单一起钉住之后,它不再依赖首屏剩余高度分配,可达性由结构保证;
/// 滚动区溢出时滚的是说明/错误行,那是可以接受被滚走的内容。
/// 滚动区溢出时滚走的是**说明/错误行**(非控件);D30 六审把说明压成单行之后,
/// 1180×760 下滚动区 ≈150px,head + 标签 + 六枚 chip + 单行说明全在首屏、**无需滚动**。
pub(crate) fn section<'a>(
ui: &'a Ui,
catalog: Catalog,
@@ -73,9 +73,22 @@ pub(crate) const ROW_PITCH: f32 = 44.0;
/// 会在 y529–530 复发残影,新标定不复发)。**改搜索条 / 表头高度时要同步这个数。**
pub(crate) const LIST_CHROME: f32 = 97.0;
/// 面板(滚动区 + 钉死区)的**最小预算**。
///
/// 滚动区要装下 head 40 + 标签 16 + 六枚 chips 32 + 说明单行 20 + 间距约 20 ≈ 128;
/// 钉死区 = 菜单 64 + 实例名 56 + 间距 16 ≈ 136。取 300 是两者之和的整档。
/// D30 五审实测:上一版「对半分」把滚动区压到 82px——宽档切「安装选项」字身、六枚 chip
/// 0 像素;窄档 24px 全被留白吃掉。
pub(crate) const PANEL_BUDGET: f32 = 300.0;
/// 正文列高度 → 列表视口的**整行高度**(只给三栏档的 Shared 分支用)。
///
/// 分高规则从「对半分」改成「**面板先保预算,剩下的按整行给列表**」:760 档
/// (正文列 580)⇒ 580 − 97 − 300 = 183 ⇒ floor(183/44)×44 = **176px = 4 整行**;
/// 900 档 ⇒ 720 − 97 − 300 = 323 ⇒ **308px = 7 整行**(五审在 900 已验 7 行)。
/// 公式不变的部分是「列表只吃整行」,变的是分子——这正是塔要的「一次性预算重分配」。
#[must_use]
pub(crate) fn whole_rows(column_height: f32) -> f32 {
let half = ((column_height - LIST_CHROME) / 2.0).max(ROW_PITCH);
(half / ROW_PITCH).floor() * ROW_PITCH
let room = (column_height - LIST_CHROME - PANEL_BUDGET).max(ROW_PITCH);
(room / ROW_PITCH).floor() * ROW_PITCH
}
+2 -2
View File
@@ -102,8 +102,8 @@ macro_rules! download_entries {
// M222:下载页只做「原版 + 加载器」一层,Forge 父链只有命令行能走。中性说明,
// 不是错误(不禁用确认键、不套错误色)——所以它不走 `problem` 那条通道。
DownloadOptionsLiteLoaderVanillaOnly => (
"LiteLoader stacks on vanilla only — for Forge, run: ull install <forge id> --loader liteloader",
"LiteLoader 只叠在原版上 —— 要叠 Forge 请运行:ull install <forge id> --loader liteloader"
"Vanilla parent only — Forge goes through the CLI",
"只叠原版;叠 Forge 请走命令行"
),
DownloadCancelled => (
"Install cancelled — finished files are kept, the instance was not created",
+1 -1
View File
@@ -106,7 +106,7 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("DownloadOptionsInstanceNameHint", "Empty = use the version id", "留空就用版本号"),
("DownloadOptionsIncompatible", "{loader} has no builds for {version}", "{loader} 没有适配 {version} 的构建"),
("DownloadOptionsNeedsAtLeast", "{loader} needs Minecraft {min} or newer", "{loader} 需要 Minecraft {min} 或更新"),
("DownloadOptionsLiteLoaderVanillaOnly", "LiteLoader stacks on vanilla only — for Forge, run: ull install <forge id> --loader liteloader", "LiteLoader 只叠在原版上 —— 要叠 Forge 请运行:ull install <forge id> --loader liteloader"),
("DownloadOptionsLiteLoaderVanillaOnly", "Vanilla parent only — Forge goes through the CLI", "只叠原版;叠 Forge 请走命令行"),
("DownloadCancelled", "Install cancelled — finished files are kept, the instance was not created", "安装已取消 —— 已下好的文件保留,实例未登记"),
("LogsSubtitleIdle", "Nothing is running right now", "当前没有运行中的实例"),
("LogsStatus", "{instance} · {when} · {outcome}", "{instance}|{when}|{outcome}"),