fix(app-iced): 选项区变高时与版本列表对半分(S1)+ 中英出图注入 + 注释同步
D30 r1 视觉驳回的三条里,代码能修的两条: 1. **S1 版面**:带加载器版本列表的选项区在三栏档把版本列表从 6.0 行压到 2.4 行(1180×760 实测 278px→110px,底缘切在第三行图标上)。`rows::TailShare::of` 现在让这类面板在**任何档位** 都与列表对半分(`scrollable` 分支早已存在),另把加载器版本菜单改成**按条目数**占高 (1 条 64px / 2 条 112px,原先只有 1 条也固定撑两行)。实测:列表回到 **245px = 5.3 行**。 2. **注释同步(S6)**:`options/view.rs` 模块头原先写「加载器分成两行」+ 两行示意,实际是 六枚一行(末枚右缘约 404px / 正文列 424);那条「本轮无看图通道,未出截图」也换成实测值。 顺带(使能中文出图):`pages/mod.rs::demo_model` 读 `ULL_DL_LANG=zh` 把 `model.lang` 与下载页 目录一起切中文。之前 `LC_ALL=zh_CN.UTF-8` 对出图**完全无效**——页面文案来自 `model.lang`, 而 `Model::new` 写死 `En`、`demo_model` 不碰它(`i18n::detect_env` 不在这条链上)。 测试:`options/s1_tests.rs` 新增两条(菜单只按整行占高;带版本列表的选项区在每个档位都 Shared, 原版/不兼容仍 Pinned),`-p unlucky-app-iced` 862 passed。 未完成:S2 窄窗「滚到底」图——iced 0.14 没有自由函数 `scroll_to`,程序化滚动要手写 `widget::Operation`(约 40 行),本轮不拿半成品充数;面板 `scrollable` 的稳定 Id 已就位。
This commit is contained in:
1 parent
841c17152a
commit
cd7813f8eb
7 files changed
+162
-18
No files matched your search
@@ -29,6 +29,8 @@
|
||||
|
||||
mod model;
|
||||
#[cfg(test)]
|
||||
mod s1_tests;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod view;
|
||||
|
||||
|
||||
@@ -308,6 +308,19 @@ impl OptionsView {
|
||||
}
|
||||
}
|
||||
|
||||
/// 面板上会不会画出**加载器版本列表**(选项区最高的那一态)。
|
||||
///
|
||||
/// 判据与 `view::show_versions` 同源(原版没有、静态不兼容没有、取不到也没有),
|
||||
/// 但这里是**纯模型查询**:`rows::TailShare::of` 要在装配前就知道面板会不会长高。
|
||||
/// 用途(M222 D30 r1 S1):带版本列表的选项区在三栏档实测把版本列表从 6 行压到 2.4 行,
|
||||
/// 于是这类面板改走「列表与面板对半分、面板自己可滚」。
|
||||
#[must_use]
|
||||
pub fn has_loader_versions(&self) -> bool {
|
||||
self.loader != Loader::Vanilla
|
||||
&& self.problem.is_none()
|
||||
&& matches!(&self.versions, LoaderVersionsView::Ready(items) if !items.is_empty())
|
||||
}
|
||||
|
||||
/// 确认安装要提交的加载器版本(`None` = 让 core 用官方默认,只在原版路径出现)。
|
||||
pub fn loader_version_arg(&self) -> Option<&str> {
|
||||
(!self.loader_version.is_empty()).then_some(self.loader_version.as_str())
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
//! M222 D30 r1(S1)的装配判据:选项区变高时怎么分高、菜单占几行。
|
||||
//!
|
||||
//! 单独一个文件是守 400 行硬线(`tests.rs` 已经装了 M105 那批兼容性/确认键的用例)。
|
||||
//! 这里的数字来自出图实测:1180×760 下版本行高 46.33px、选项区从 204px 长到 372px 时
|
||||
//! 版本列表从 6.0 行被压到 2.4 行。
|
||||
|
||||
use unlucky_i18n::Lang;
|
||||
use unlucky_presenter::dto::{LoaderKind, VersionKind};
|
||||
use unlucky_presenter::state::AppState;
|
||||
|
||||
use super::model::{Loader, OptionsView};
|
||||
use super::tests::{draft, row, state_with};
|
||||
|
||||
/// S1 的前置:加载器版本菜单**只按条目数占高**(一行为 64、两行为 112),不空撑两行。
|
||||
///
|
||||
/// 抓得住:菜单高度改回「固定两行」(LiteLoader 只有 1 条版本时白占 48px,正好把上面版本
|
||||
/// 列表挤掉一行);或者有人把留白算丢(高度不是 64/112 这两个整行值,菜单项会被截半行)。
|
||||
#[test]
|
||||
fn version_menu_height_counts_whole_items_only() {
|
||||
use super::view::version_menu_height;
|
||||
assert_eq!(version_menu_height(0), 64.0, "空表也按一行占(不塌成 0)");
|
||||
assert_eq!(version_menu_height(1), 64.0, "一条版本 = 一行项 + 上下留白");
|
||||
assert_eq!(version_menu_height(2), 112.0, "两条 = 两行");
|
||||
assert_eq!(
|
||||
version_menu_height(50),
|
||||
112.0,
|
||||
"再多也只露两行(余下靠菜单内滚动)"
|
||||
);
|
||||
}
|
||||
|
||||
/// S1(D30 r1)的装配判据:**带加载器版本列表**的选项区在任何档位都与列表对半分。
|
||||
///
|
||||
/// 实测背景(1180×760):选项区从 204px 长到 372px 时,版本列表被压成 2.4 行(110px),
|
||||
/// 底缘切在第三行图标上;对半分之后列表回到 4.6 行、面板自己可滚。
|
||||
///
|
||||
/// 抓得住:有人把这条规则删掉(`TailShare::of` 只判 chips 档)——列表又会掉回 2 行;
|
||||
/// 或者把它放宽成「任何选项区都对半分」(原版没有版本列表时不该对半分,那会把 6 行列表
|
||||
/// 砍成 4 行)。
|
||||
#[test]
|
||||
fn tall_options_panel_shares_height_at_every_tier() {
|
||||
use crate::pages::download::install::PanelState;
|
||||
use crate::pages::download::rows::TailShare;
|
||||
use crate::pages::layout::VersionRailTier;
|
||||
|
||||
let version_row = row("1.12.2", VersionKind::Release);
|
||||
let with_versions = state_with(
|
||||
LoaderKind::LiteLoader,
|
||||
"1.12.2",
|
||||
Ok(vec!["1.12.2-SNAPSHOT"]),
|
||||
);
|
||||
let tall = OptionsView::of(
|
||||
&version_row,
|
||||
&with_versions,
|
||||
&draft(Loader::LiteLoader),
|
||||
Lang::En.catalog(),
|
||||
);
|
||||
assert!(tall.has_loader_versions(), "LiteLoader 有版本列表");
|
||||
for tier in [
|
||||
VersionRailTier::Wide,
|
||||
VersionRailTier::Narrow,
|
||||
VersionRailTier::Compact,
|
||||
VersionRailTier::Chips,
|
||||
] {
|
||||
assert_eq!(
|
||||
TailShare::of(tier, &PanelState::Options(&tall)),
|
||||
TailShare::Shared,
|
||||
"{tier:?}:带版本列表的选项区必须与列表对半分"
|
||||
);
|
||||
}
|
||||
|
||||
// 原版没有版本列表 ⇒ 仍然钉死(三栏档不该无谓对半分)。
|
||||
let plain_state = AppState::new();
|
||||
let plain = OptionsView::of(
|
||||
&version_row,
|
||||
&plain_state,
|
||||
&draft(Loader::Vanilla),
|
||||
Lang::En.catalog(),
|
||||
);
|
||||
assert!(!plain.has_loader_versions());
|
||||
for tier in [VersionRailTier::Wide, VersionRailTier::Compact] {
|
||||
assert_eq!(
|
||||
TailShare::of(tier, &PanelState::Options(&plain)),
|
||||
TailShare::Pinned,
|
||||
"{tier:?}:原版选项区没有版本列表,钉死"
|
||||
);
|
||||
}
|
||||
|
||||
// 不兼容(有 problem)时列表不画 ⇒ 也不该对半分。
|
||||
let blocked_state = state_with(LoaderKind::LiteLoader, "1.13", Ok(Vec::new()));
|
||||
let blocked = OptionsView::of(
|
||||
&row("1.13", VersionKind::Release),
|
||||
&blocked_state,
|
||||
&draft(Loader::LiteLoader),
|
||||
Lang::En.catalog(),
|
||||
);
|
||||
assert!(!blocked.has_loader_versions(), "不兼容时没有版本列表");
|
||||
}
|
||||
@@ -16,7 +16,7 @@ use unlucky_presenter::state::AppState;
|
||||
use super::model::{release_rank, Incompat, InstallDraft, Loader, LoaderVersionsView, OptionsView};
|
||||
use crate::pages::download::model::VersionRow;
|
||||
|
||||
fn row(id: &str, kind: VersionKind) -> VersionRow {
|
||||
pub(super) fn row(id: &str, kind: VersionKind) -> VersionRow {
|
||||
VersionRow::of(
|
||||
&VersionSummary {
|
||||
id: id.to_string(),
|
||||
@@ -28,7 +28,7 @@ fn row(id: &str, kind: VersionKind) -> VersionRow {
|
||||
)
|
||||
}
|
||||
|
||||
fn state_with(kind: LoaderKind, mc: &str, items: Result<Vec<&str>, &str>) -> AppState {
|
||||
pub(super) fn state_with(kind: LoaderKind, mc: &str, items: Result<Vec<&str>, &str>) -> AppState {
|
||||
let mut state = AppState::new();
|
||||
state.apply(AppEvent::Core(CoreEvent::LoaderVersions {
|
||||
kind,
|
||||
@@ -44,7 +44,7 @@ fn state_with(kind: LoaderKind, mc: &str, items: Result<Vec<&str>, &str>) -> App
|
||||
state
|
||||
}
|
||||
|
||||
fn draft(loader: Loader) -> InstallDraft {
|
||||
pub(super) fn draft(loader: Loader) -> InstallDraft {
|
||||
InstallDraft {
|
||||
selected: Some("1.20.1".to_string()),
|
||||
loader,
|
||||
|
||||
@@ -5,21 +5,22 @@
|
||||
//! ```text
|
||||
//! 1.21.9 [安装]
|
||||
//! 安装选项
|
||||
//! [原版][Forge][NeoForge]
|
||||
//! [Fabric][Quilt]
|
||||
//! [原版][Forge][NeoForge][Fabric][Quilt][LiteLoader] ← 六枚一行
|
||||
//! LiteLoader 只叠在原版上 —— 要叠 Forge 请运行:… ← 中性说明(只有 LiteLoader 有)
|
||||
//! 加载器版本 ← 只在选了加载器时出现
|
||||
//! ┌ 0.16.5 ┐ ← 官方那份列表(menu + 滚动,最多看两行)
|
||||
//! ┌ 0.16.5 ┐ ← 官方那份列表(menu + 滚动,最多看两行项)
|
||||
//! │ 0.16.4 │
|
||||
//! └───────────────────┘
|
||||
//! [实例名 ]
|
||||
//! NeoForge 需要 Minecraft 1.20.1 或更新 ← 不兼容时(Error 色)
|
||||
//! ```
|
||||
//!
|
||||
//! ## 为什么加载器分成两行
|
||||
//! ## 为什么加载器是**六枚一行**(M222 D30 r1 实测订正)
|
||||
//!
|
||||
//! 五家一起排在 424 宽里最宽的那组(`原版 + Forge + NeoForge + Fabric + Quilt`)实测会溢出,
|
||||
//! 而 chip 的几何是组件自己的真源(`ChipGeometry`),页面不许压它 ⇒ 折成两行。
|
||||
//! 顺序仍是任务书的口径(原版 / Forge / NeoForge / Fabric / Quilt),只是换行。
|
||||
//! 这里原先写「五家一起排会溢出 ⇒ 折成两行」,那是 M105 的推算。D30 的实测图(1180×760,
|
||||
//! 正文列 424)是**六枚一行、末枚右缘约 404px**,没有溢出——所以示意与说明都改成了实际形态。
|
||||
//! chip 的几何仍是组件自己的真源(`ChipGeometry`),页面不许压它;再来第七家时先看图再决定
|
||||
//! 是否换行。
|
||||
//!
|
||||
//! ## 为什么「不兼容」不禁用 chip、而是禁用确认键
|
||||
//!
|
||||
@@ -50,12 +51,20 @@ use super::model::{Loader, LoaderVersionsView, OptionsView};
|
||||
// 加载器 chip 的顺序与集合**委派**给 `Loader::ALL`(原版 / Forge / NeoForge / Fabric /
|
||||
// Quilt / LiteLoader)。这里原先是手写的五枚常量——同一份清单的第三处副本
|
||||
// (`dto::wizard_choices`、`Loader::ALL`、这里),M222 加 LiteLoader 时三处都得改,索性委派。
|
||||
// ⚠️ 宽度需 D30 视觉复验:五枚 chip 实测合计约 311 dp(正文列 424),第六枚估算 +50 dp,
|
||||
// 理论仍在行内,但那是估算不是实测(本轮无看图通道,未出浅/深色截图)。
|
||||
// D30 r1 实测(1180×760 与 720×760 两种宽度、浅/深两套主题):六枚 chip 排在一行,
|
||||
// 末枚(LiteLoader)右缘约 404px,正文列 424 仍有余量;窄窗 720 下同一行也没有溢出。
|
||||
|
||||
/// 菜单项高度 = 48(`MenuGeometry` 的项高)×2 行 + 上下留白 8×2 = 112。
|
||||
/// 这么算是为了避免「列表被截掉半行」——滚动区高度必须覆盖整行。
|
||||
const VERSION_ROWS: f32 = 7.0;
|
||||
/// 加载器版本菜单的**可见高度**(像素):最多两行项 + 上下留白 8×2。
|
||||
///
|
||||
/// 项高 48 是 `MenuGeometry` 的真源;`Space::X2 = 8` 是上下留白 ⇒ 两行 = 112、一行 = 64。
|
||||
/// 为什么按**条目数**取(M222 D30 r1 S1):LiteLoader 对 1.12.2 只有一条版本,原来固定撑到
|
||||
/// 两行高(112px),那 48px 纯属空档,却正好是把上面版本列表挤成 2.4 行的元凶之一。
|
||||
/// 单测 `options/view::tests` 直接钉这两档的数值。
|
||||
pub(super) fn version_menu_height(items: usize) -> f32 {
|
||||
const ITEM: f32 = 48.0;
|
||||
let rows = items.clamp(1, 2) as f32;
|
||||
rows * ITEM + Space::X2.dp() * 2.0
|
||||
}
|
||||
|
||||
/// 选项区(面板的下半块)。
|
||||
pub(crate) fn section<'a>(
|
||||
@@ -196,7 +205,7 @@ fn version_list<'a>(
|
||||
list = list.item(entry);
|
||||
}
|
||||
scrollable(menu(ui, list))
|
||||
.height(Length::Fixed(ui.space(Space::X4) * VERSION_ROWS))
|
||||
.height(Length::Fixed(version_menu_height(items.len())))
|
||||
.style(frame::scroll_style(ui))
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ pub(super) fn content<'a>(
|
||||
let tail: Element<'a, Message> = match share {
|
||||
TailShare::Pinned => tail,
|
||||
TailShare::Shared => scrollable(tail)
|
||||
.id(iced::widget::Id::new(PANEL_SCROLL_ID))
|
||||
.height(Length::Fill)
|
||||
.style(frame::scroll_style(ui))
|
||||
.into(),
|
||||
@@ -129,6 +130,12 @@ pub(super) fn content<'a>(
|
||||
.into()
|
||||
}
|
||||
|
||||
/// 面板那一层 `scrollable` 的 Id(M222 D30 r1 S2 的出图取证用,见 `pages::harness`)。
|
||||
///
|
||||
/// 用途只有一个:窄窗(chips 档 / 带版本列表的选项区)里面板自己可滚,出图要证明
|
||||
/// 「实例名那格滚得到」——harness 拿到这个 Id 就能派一次 `scroll_to` 再拍。
|
||||
pub(crate) const PANEL_SCROLL_ID: &str = "download-panel";
|
||||
|
||||
/// 列表与尾部面板怎么分这块高度(M125 缺陷 1 的修法)。
|
||||
///
|
||||
/// | 档 | 分法 | 为什么 |
|
||||
@@ -159,11 +166,16 @@ impl TailShare {
|
||||
/// 掉到 **4 整行**、下半块留 ≈160px 空画布(r1 复审 P2-1 实测:main 在 700×760 的
|
||||
/// `Hint` 态是 7 整行——不是 8,第 8 条墨迹其实是 `Pick a version, then install` 那句
|
||||
/// hint,横向范围对不上版本号;r2 修回 7 整行)。所以 `Hint` **在任何档位都钉死**。
|
||||
pub(super) const fn of(tier: VersionRailTier, state: &PanelState<'_>) -> Self {
|
||||
pub(super) fn of(tier: VersionRailTier, state: &PanelState<'_>) -> Self {
|
||||
match (tier, state) {
|
||||
(VersionRailTier::Chips, PanelState::Options(_) | PanelState::Install(_)) => {
|
||||
Self::Shared
|
||||
}
|
||||
// M222 D30 r1 S1:**带加载器版本列表**的选项区在任何档位都太高。三栏档实测
|
||||
// (1180×760)面板从 204px 涨到 372px,版本列表从 6.0 行(278px)被压到 2.4 行
|
||||
// (110px)——列表底缘还切在第三行图标上。改成 Shared:两半各 ≈215px,
|
||||
// 列表回到 4.6 行,面板自己可滚([`Self::Shared`] 那条 `scrollable` 分支已存在)。
|
||||
(_, PanelState::Options(options)) if options.has_loader_versions() => Self::Shared,
|
||||
_ => Self::Pinned,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,9 +323,20 @@ pub fn app_with_appearance<'a>(
|
||||
/// 真的传进来,否则「矮窗口那几张图」画的是高窗口的版面。
|
||||
pub fn demo_model(screen: Screen, window_width: f32, window_height: f32) -> Model {
|
||||
let mut model = Model::new(screen, window_width, window_height, Some(screen.nav()));
|
||||
// 出图的中英取证(M222):`ULL_DL_LANG=zh` 时整页走中文目录。
|
||||
//
|
||||
// 为什么需要这一行:页面文案来自 `model.lang`(`download::view(.., lang)` → `lang.catalog()`),
|
||||
// 而 `Model::new` 的 `lang` 写死 `En`、`demo_model` 之前也不碰它——所以 `LC_ALL=zh_CN.UTF-8`
|
||||
// 对出图**完全无效**(`i18n::detect_env` 不在这条链上,Windows 上平台源还会压过 env)。
|
||||
// 只有 harness / 单测走 `demo_model`,产品路径由 `app/view.rs` 从 `AppState` 建模型,零影响。
|
||||
let lang = match std::env::var("ULL_DL_LANG").ok().as_deref().map(str::trim) {
|
||||
Some("zh" | "zh_cn" | "zh-CN" | "zh_CN") => unlucky_i18n::Lang::ZhCn,
|
||||
_ => unlucky_i18n::Lang::En,
|
||||
};
|
||||
model.lang = lang;
|
||||
match screen {
|
||||
Screen::Instances => model.instances = instances::demo(),
|
||||
Screen::Download => model.download = download::demo(unlucky_i18n::Lang::En.catalog()),
|
||||
Screen::Download => model.download = download::demo(lang.catalog()),
|
||||
Screen::Content => model.content = content::demo(content::ContentKind::Mod, model.lang),
|
||||
Screen::Logs => model.logs = logs::demo(model.lang),
|
||||
// M159:设置页「更新」组的出图夹具(一个可装的新版本 + 一次成功检查)。
|
||||
|
||||
Reference in new issue
Block a user