AskaEth
|
0eb069fa37
|
fix(app-iced): M95 r4 —— 归属判据回归 / 置信度档 / 运行中页头
代码复审 r3 的四条 p2,修三条、登记一条(P2-4 页脚余量 13px,后置)。
**P2-1(回归修复)**:r3 把归属判据写成「有选中就只认选中」,把**导入崩溃文件**与 `open_session`
这两条路径的诊断一并关掉了——`559ba20` 是**无条件**画的,所以这是 r3 引入的**代码级回归**,
不是既有缺口(今天 iced 侧没有 dispatch 站点,那些还在遗留的 Slint shell 里,故复审未判 p1)。
判据改成三分支(`app/view/logs.rs`):
| live_session | selected_session | 报告算数的条件 |
|---|---|---|
| Some(s) | 任意 | `report.session == s`(只有它在线时日志行是它在追加,别人的报告挂上来就是串场) |
| None | Some(s) | `report.session == s` **或** 报告不属于任何已知会话(导入用 `file:<文件名>`,永不在索引里) |
| None | None | 全部算数(此时日志行只可能来自 `open_session`/导入,与报告同一次调用发出) |
新增两条测试(都走真实 reducer):`an_imported_crash_file_still_shows_its_findings`、
`a_live_run_says_it_is_running_instead_of_nothing_runs`。
残留(今天不可达,已登记):`open_session(A)` 在 `selected_session` 仍停在上场 B 时会被挡掉——
真要修得让 presenter 在 `LogLinesChanged` 记下「日志行属于哪一场」。
**P2-2 置信度档(视觉变更)**:`Severity`(借 core 的 `critical/warning/notice` 词汇)→
`Confidence`(`High/Medium/Low`)+ 新 key `LogsConfidenceHigh/Medium/Low`(中英齐,标题明确写
「高/中/低置信度」)。阈值仍是 80/50,但它现在是**档位定义**而不是「严重度代理」。
摘要里的 `findings=rule:high(85)` 同步换档位 slug。DTO 补齐 `severity` 之后应换回真严重度(finding)。
**P2-3 运行中的页头**:session 索引只在**结束**时追加,运行中的那一场不在 `log_sessions` 里 ⇒
拿不到实例名与结局 ⇒ r3 之前页头在日志滚动时一直说「当前没有运行中的实例」(demo 伪造了身份,
截图照不出来)。`Logs` 新增 `live: bool`(`live_session.is_some()`),`with_status` 三级回退:
有实例+结局 → `实例 · 时间 · 结局`;运行中但没结局 → 新 key `LogsSubtitleLive`(「Running now —
logs stream as they arrive」);都没有 → `LogsSubtitleIdle`。
新增 `a_live_run_says_it_is_running_instead_of_nothing_runs`(真实 reducer:只有
`LogAppended(running=true)`,断言副标题不是 Idle 文案且含 `Running now`)。
新增 demo 状态 `ULL_LOGS_FIXTURE=running` 用于出图。
**变异实测**(每条:回退 → 红 → 放回 → 绿):见报告。
验证:`fmt --check` 通过;`clippy -p unlucky-app-iced -p unlucky-i18n --all-targets -D warnings` 干净;
`cargo test` **280 + 6 + 23 passed / 0 failed**;行数最大 `pages/mod.rs` 367、`app/view.rs` 324、
`app/view/logs.rs` 337。
|
2026-11-02 22:27:01 +08:00 |
|
AskaEth
|
5ed2bf3a7d
|
fix(app-iced): M95 r3 摘要页脚占比 4:2 + 演示数据自洽 + 样例解析不再 panic
视觉复审 r2 的 P2-A 与两个顺手的 p3。
**P2-A 摘要页脚占比过大(3:2 → 4:2)**:1180×760 下诊断卡 338px,摘要页脚固定吃掉 ~150px
(标签+按钮 40 + 摘要折 5 行 80 + 间距/分割 30),滚动视口只剩 141px,而一条完整结论
(分组标题 → 建议动作 → 置信度)要 165px ⇒ 首屏看不到「建议动作」,那是任务清单 T1/T3 要求的
可见项。改成 `DIAGNOSIS_SHARE = 4`(`LOGS_SHARE` 仍 2)。**数值实测**(`r3-crash-light.png`
逐像素量,非估算):诊断卡 376px、滚动视口 **178px**(y 201–378,两侧 1px 分割线的位置)、
一条完整结论块 **165px**、底部余量 **13px** —— 建议动作与 `Confidence 85%` 整块在首屏可见。
**p3 演示数据自相矛盾**:`live` 状态页头写「Finished normally」却配崩溃日志尾行
(`启动失败:exit code 1`)。新增 `sample_live.log`(一场正常跑完的会话:加载 → 进世界 →
停服),`State::Live` 用它,不再复用崩溃样例。
**p3 `demo::parse` 对非 ASCII 首字符 panic**:`raw.split_at(1)` 会切在多字节序列中间。
改成按字符取前缀(`chars().next()` + `chars.as_str()`);顺带把它提成 `pub(super)` 以便测。
新增 `the_fixture_parser_survives_a_non_ascii_first_char`:非 ASCII 首字符不 panic(静默跳过),
并钉住 `I/W/E` 前缀与注释/空行的解析。
测试:**278 passed / 0 failed**(lib)+ 6(`no_hardcoded_tokens`)+ 23(i18n)全绿;
`fmt --check` 通过;`clippy -p unlucky-app-iced -p unlucky-i18n --all-targets -D warnings` 干净。
出图:`C:\Temp\ull-shots-m95\r3-{crash-light,crash-dark,live-light,empty-light}.png`(1180×760)。
|
2026-11-02 22:27:00 +08:00 |
|
AskaEth
|
1bccf89e5c
|
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 证据)。
|
2026-11-02 22:26:59 +08:00 |
|
AskaEth
|
063a1dba39
|
feat(app-iced): M95 日志页接真组件 + 诊断面板(等宽折行 / 按严重度分组 / 一行摘要)
日志页从 M84 占位换成真组件,数据全部来自 presenter 快照(页面不读盘):
- 日志行列表:`pages/logs/lines.rs`,等宽(`BodySmall` 12/16 + mono 族)+ 按词或字形
折行 + 等级色条;**选折行不选横滚**的理由写在模块文档(424px × 200 字符的现实 +
mono 族的 CJK 回退会毁掉横滚唯一的收益「列对齐」)。
- 诊断面板:`pages/logs/diagnostic.rs`,按严重度分组(CRITICAL → WARNING → NOTICE),
每条给规则 id / 结论 / 说明 / 建议动作 / 置信度;卡片头钉住「Copy summary」,
摘要是稳定单行的 `ULL-LOGS v1 | …`(崩溃日志换 issue 时直接粘)。
- 空态:真组件 `feedback::EmptyState`(图标块 + 标题 + 说明 + CTA 回实例页)。
- 两块都在 `pages/logs/panel.rs` 里**定高 + 内部独立滚动**(`FillPortion(3):(2)`):
第一版让诊断卡按内容撑开,三条结论就把日志卡压成 0 高度(实拍复现后改的)。
- 视图模型:`pages/logs/model.rs`(纯展示字段)+ `app/view.rs::logs_model` 做快照转换。
- 接线(只追加):`pages/mod.rs` 的 `pub use logs::…` / `page()` 那行 /
`Message::CopySummary` / `demo_model` 一行;`pages::Model` 加 `logs` 与 `lang` 两个字段;
`app/update.rs` 把 `CopySummary` 落到 `iced::clipboard::write`、`ClearLogs` 清 presenter 的
`log_lines`(呈现层操作,不造命令)。
- i18n:`crates/i18n/src/catalog.rs` 自己锚点下 16 个 key(中英同表);按塔裁决把
`#[cfg(test)] mod tests` 逐字外置到 `crates/i18n/src/catalog/tests.rs`
(catalog.rs 415 → 257 行,tests.rs 164 行;7 个用例逐字未动、i18n 23 个用例全绿)。
验证:`fmt --check` / `clippy -p unlucky-app-iced --all-targets -- -D warnings` 干净;
`test -p unlucky-app-iced` 272 + 6 全绿、`-p unlucky-i18n` 23 全绿;截图
`.screens/logs-{empty,crash,live}-{light,dark}.png`(1180×760,本地 gitignore)。
遗留(已报 finding):`dto::Diagnosis` 缺 core 的 `severity` 与规则表 `cause.key`;
`Action::OpenLogs` 没有对应 `AppCommand`(点了只有占位日志)。
|
2026-11-02 22:26:53 +08:00 |
|