AskaEth
f03411d58b
fix(instances): M302 r1 P2 —— 冷启动首帧三态(占位 / 真空态 / 有实例)+ N1~N4
复审 P2-1:扫盘搬后台之后,`App::dispatch(RefreshAll)` 返回时快照还没到(`pump` 只抽队列、
不 `tick`),**首帧必然**在快照之前。改前那一帧画的是「计数 0 + 还没有实例 + 实心导入 CTA」
——一句假话,而且 CTA 能点。改后三态分开:
- 真源放 presenter:`dto::InstancePhase { Scanning, Stalled, Ready }`,`AppState::instances_phase`
在 `CoreEvent::InstancesChanged` 落地时置 `Ready`;**不从 `instances.is_empty()` 推**(那就是 bug 形态)。
- `Scanning` = 首个快照未到:详情列画「正在扫描实例…」占位(新 key `InstancesScanning`,golden 两语),
列头**不写计数**(藏起来,不写 0 也不写「—」),**没有**空态 CTA。
- `Stalled` = 有界兜底:`host::game::SCAN_STALL = 15 s`(= 仓库内最坏实测 1.35 s 的约 11 倍,
理由在常量文档里)。超时只**报**一次、不掐线程;迟到的结果照样落地(代次没变)。
那一屏给一枚「重新扫描」→ `InstanceMessage::RetryScan` → 新命令 `AppCommand::RefreshInstances`
(只重扫实例目录,不重拉版本清单)。那一支在 `selected_instance_id()` 守卫**之前**——冷启动没有选中项。
- `Ready` = 收到过快照(空列表也算):这时才轮到 M273 的两种空态(没选中 / 一个都没有)。
- 已就绪时**不发** `Scanning`:否则每次刷新列表都退回占位(把卡顿换成闪屏)。
判据(都能红,变异原文见报告):
- `pages/instances/tests/cold_boot.rs`:真控件树(未就绪 7 枚按钮 = 有实例那一屏,零实例 = 8 枚,
多的那枚就是 CTA;每行 2 条文字节点的差分数行数)+ 源码结构(`Scanning`/`Stalled` 两支不碰
`detail_empty` 与空态文案、超时那支接 `RetryScan`、三个 key 真的被读)。
- `app/update/instances/scan_phase.rs`:首帧 = `Scanning`、空快照 = `Ready`、`Stalled` 经重试回到
`Scanning`、重试只派 `RefreshInstances`。夹具 `ULL_INSTANCE_PHASE` 只给出图(与 `ULL_SAVES_FIXTURE` 同一条纪律)。
顺手收 N1~N4(全是措辞 / 观测口径,不动行为):
- N1 两处 docstring 不再声称「`admit` 写成 `>=` 会红」(实测等价),改成「去掉或恒真才红」;
- N2 收尾用例那条 Idle 断言的失败消息改准(它不区分新旧快照,区分靠条数/代次断言);
- N3 boot 双刷新必然丢 1 份 ⇒ 丢弃日志分成「此前没有快照落地(启动期,非交错)」与「已有落地(真交错)」,
`Scan::dropped` 的文档登记这条已知噪音;
- N4 app 用例 docstring 收窄成「一拍无事件不清表、不钉时钟」(它绕过 `App::dispatch`,抓不住那 5 行)。
拆文件守 400 行:`detail/scan.rs`(分派 + 占位)、`refresh_stall_tests.rs`(空根 / 超时)、
`app/update/instances/scan_phase.rs`(app 级三态用例);`i18n` 的 `PAGE_SOURCES` 同步加上新页面文件。
2026-11-13 19:00:30 +08:00
..
2026-11-11 06:53:52 +08:00
2026-11-12 19:55:51 +08:00
2026-11-10 19:37:23 +08:00
2026-11-13 19:00:30 +08:00
2026-11-10 19:34:09 +08:00
2026-11-13 13:18:11 +08:00
2026-11-11 10:48:16 +08:00
2026-11-10 21:09:37 +08:00
2026-11-11 17:09:17 +08:00
2026-11-13 11:10:30 +08:00
2026-11-11 06:53:52 +08:00
2026-11-09 05:06:55 +08:00
2026-11-10 19:37:23 +08:00
2026-11-07 17:28:36 +08:00
2026-11-13 19:00:30 +08:00
2026-11-09 05:24:11 +08:00
2026-11-12 19:55:52 +08:00
2026-11-13 17:58:59 +08:00
2026-11-13 19:00:30 +08:00
2026-11-07 15:02:13 +08:00
2026-11-02 09:29:31 +08:00
2026-11-09 18:42:41 +08:00
2026-11-09 18:42:41 +08:00
2026-11-04 22:12:22 +08:00
2026-11-10 19:34:12 +08:00
2026-11-10 19:37:41 +08:00
2026-11-12 19:55:51 +08:00
2026-11-13 17:58:59 +08:00
2026-11-12 19:55:51 +08:00
2026-11-13 17:58:59 +08:00
2026-11-13 13:50:41 +08:00
2026-11-04 22:12:22 +08:00
2026-11-09 14:12:23 +08:00
2026-11-11 09:19:42 +08:00
2026-11-04 22:12:22 +08:00
2026-11-13 19:00:30 +08:00
2026-11-12 19:55:51 +08:00
2026-11-02 09:29:31 +08:00
2026-11-12 19:55:51 +08:00
2026-11-09 05:24:12 +08:00
2026-11-09 18:42:41 +08:00
2026-11-07 15:02:13 +08:00
2026-11-07 15:02:13 +08:00
2026-11-08 09:30:05 +08:00
2026-11-09 09:49:41 +08:00
2026-11-08 11:12:10 +08:00
2026-11-02 09:29:31 +08:00