fix(app-iced): M95 r1 五条视觉复审(悬挂缩进 / 会话身份 / 摘要可见 / 贴底 / 描边)

- P2-1 **悬挂缩进真做了**(之前文档在骗人,代码里只有 `row![bar, text]`):
  每行拆「前缀 + 正文」两个文本控件(前缀 = 第一个空格及其之前,含空格;
  `split_prefix` 在第一个「词」>20 字符时不拆),正文带 Fill 宽度自己折行 ⇒
  续行落在前缀宽度之后。于是 `at com.mojang…(GLX.java:64)` 不再拆成「`at` 独占一行」。
  文档同步写清代价:续行缩进量 = 该行前缀宽度。
- P2-2 会话身份上页头:`Logs::with_status(lang)` 用 `LogsStatus` 模板拼
  `{instance} · {when} · {outcome}`,结局文案走 `LaunchOutcomeNormal/Crash/Silent`
  三 key(bridge 文档里那条「LogOutcome 三态 → 三 key」的结构化出口,此前 UI 侧零调用点)。
  中文模板差在全角竖线(守卫要求 zh≠en,也确实更符合中文排版)。
- P2-3 摘要钉成诊断卡**固定页脚**(不进滚动区):「One-line summary」+ Copy summary
  紧邻它要复制的那段等宽文本;卡片头不再放复制按钮(避免两处入口)。
- P2-4 日志卡改 `panel::scroll_tail`(`Anchor::End`):偏移按「距底多远」记,内容增长时
  跟随尾部;「用户上滚后是否冻结」的边界写在 `panel::scroll_tail` 文档里(结论:不冻结,
  冻结要 app 层回灌滚动状态,已登记)。
- P2-5 两张主卡补 1px 描边:`panel::card` 改用 `Component::OutlinedCard.spec().shape` +
  `ui.outlined(..)`,与 `frame::card` 同一套令牌。

测试:新增 `a_line_is_split_into_prefix_and_body_for_the_hanging_indent`(含 CJK 行与
「不拆」的两种边界)与 `status_line_names_the_session_with_the_launch_outcome_keys`;
key 清单补 `LogsStatus` 与三个 `LaunchOutcome*`;demo 的 state.build 改为收 `Lang`。

验证:`fmt --check` 通过;`clippy -p unlucky-app-iced --all-targets -D warnings` 干净;
`test -p unlucky-app-iced` 274+6 全绿、`-p unlucky-i18n` 23 全绿。
图:`.screens/logs-{empty,live,crash}-{light,dark}.png`(1180×760)、
`r2-live-tall-light.png`(1180×1080,栈帧可见,P2-1 证据)。
This commit is contained in:
AskaEth committed 2026-11-02 22:26:59 +08:00
1 parent 063a1dba39
commit 1bccf89e5c
10 files changed
+293 -93

No files matched your search

+13 -7
View File
@@ -24,6 +24,8 @@
//! **中文在这里是「规则表的输出(数据)」,不是界面文案**:界面文案(标题 / 按钮 / 分组名 /
//! 空态)全部走 `unlucky_i18n` 的 key,见 `logs.rs`。
use unlucky_i18n::Lang;
use super::model::{Finding, Level, Line, Logs, Outcome, Severity};
/// 挑演示状态的环境变量。
@@ -54,28 +56,31 @@ impl State {
}
}
/// 造出这个状态的视图模型。
/// 造出这个状态的视图模型(`lang` 用于页头副标题的 i18n)。
#[must_use]
pub fn build(self) -> Logs {
pub fn build(self, lang: Lang) -> Logs {
match self {
Self::Empty => Logs::default(),
Self::Empty => Logs::default().with_status(lang),
Self::Live => Logs {
outcome: Some(Outcome::Ok),
findings: Vec::new(),
..crash()
},
Self::Crash => crash(),
}
.with_status(lang),
Self::Crash => crash().with_status(lang),
}
}
}
/// harness 入口:按 [`STATE_ENV`] 挑状态。
#[must_use]
pub fn demo() -> Logs {
State::of_env_value(std::env::var(STATE_ENV).ok().as_deref()).build()
pub fn demo(lang: Lang) -> Logs {
State::of_env_value(std::env::var(STATE_ENV).ok().as_deref()).build(lang)
}
/// 崩溃现场(日志 + 三条诊断,覆盖 critical / warning 两个分组)。
///
/// 不带 `status`(副标题要 i18n,见 [`Logs::with_status`]):[`State::build`] 会补上。
#[must_use]
pub fn crash() -> Logs {
Logs {
@@ -84,6 +89,7 @@ pub fn crash() -> Logs {
outcome: Some(Outcome::Crashed),
lines: parse(SAMPLE),
findings: findings(),
..Logs::default()
}
}