fix(launch): M298 收尾失败不再静默、Toast 接上渲染点
三条提示通道各漏一半,用户才会「启动失败但找不到崩溃日志」: 1) 收尾失败静默不弹:finish() 报错那条出口把 LaunchFinished.session 发成真实 会话,而它登记的现场走 before_start 写死空串 ⇒ dialog.rs 的并发守卫 (!finished.session.is_empty() && report.session != finished.session)成立后 return。改成**会话归属单一来源**:before_start 新增可选 SessionAttribution, presenter 的 publish_before_start 把它写进报告后**返回同一个值**给 DTO; 两处不可能再各写一遍。守卫原样保留(A 场的现场不许解释 B 场,有用例钉住)。 2) Toast 只 push 不渲染:新增 app/view/toast.rs 覆盖层(MD3E 胶囊 = ShapeScale::Full,底部居中,InverseSurface 底),接在页面树之上、模态之下; 过期仍走 clock.rs 的 expire;进/出过渡复用模态那一对腿(motion::modal_spec / modal_scale / scaled),时间轴在 update 侧由 state/toast.rs 采样,关掉动效时 恒为终值(出图可复现)。两个拷贝路径补上 view_dirty(推了不置脏要等下一次事件)。 3) 三个贴线文件先拆再改(纯搬移 + pub use 保路径,机器核对:搬出的 14 个函数体 逐行相同):crash_report.rs 394→318(+context.rs / slot.rs)、 host/launch.rs 399→233(+build.rs)、app/dialog.rs 390→178(+model.rs)。 证据:DevDocs/artifacts/m298/toast-capsule.png(--screenshot + ULL_TOAST_FIXTURE, 图上可见「游戏崩溃 · 12.0 秒」胶囊)。
This commit is contained in:
1 parent
fc8f5c6794
commit
97768b7e3f
19 files changed
+1699
-553
No files matched your search
@@ -0,0 +1,48 @@
|
||||
//! 出图取证用的 Toast 夹具(`ULL_TOAST_FIXTURE`;产品路径零影响)。
|
||||
//!
|
||||
//! # 它解决什么
|
||||
//!
|
||||
//! M298 的交付图要证明「提示真的画在窗口底部」,而产品路径的 toast 由事件推出来
|
||||
//! (安装取消 / 启动收尾 / 复制成功),截图通道在第 3 帧就出图:等不到那条事件。
|
||||
//! 处理方式与 `mods_shot` / `saves_shot` 一致——**状态注入**,注在「快照 → 页面模型」之前,
|
||||
//! 于是覆盖层、胶囊几何、i18n 文案走的都是产品代码。
|
||||
//!
|
||||
//! # 边界(不要把它读成产品能力)
|
||||
//!
|
||||
//! - 只在环境变量存在时生效(`ULL_TOAST_FIXTURE` 非空且不为 `0`);
|
||||
//! - 推的是**一条真实形状的提示**:文案由产品函数 `launch_toast` 按**生效语言**现求,
|
||||
//! 不是夹具里写死的一句中文;
|
||||
//! - 剩余寿命走 `ToastCenter` 的默认 TTL(4 s),过期仍由 `app/update/clock.rs` 的 `expire` 管。
|
||||
|
||||
use unlucky_presenter::dto::{LaunchFinished, LogOutcome};
|
||||
use unlucky_presenter::toast::ToastKind;
|
||||
|
||||
use super::App;
|
||||
|
||||
/// 夹具开关是否打开(`ULL_TOAST_FIXTURE` 非空且不为 `0`)。
|
||||
fn enabled() -> bool {
|
||||
std::env::var("ULL_TOAST_FIXTURE")
|
||||
.map(|value| {
|
||||
let value = value.trim();
|
||||
!value.is_empty() && value != "0"
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// 推一条「游戏崩溃」的收尾提示(就是用户在真机上看到的那一句)。
|
||||
pub(super) fn seed(app: &mut App) {
|
||||
if !enabled() {
|
||||
return;
|
||||
}
|
||||
// 形状取自真实收尾事件:崩溃 + 退出码 1 + 跑了 12 秒。
|
||||
let finished = LaunchFinished {
|
||||
id: "survival".to_string(),
|
||||
session: String::new(),
|
||||
outcome: LogOutcome::Crashed,
|
||||
exit_code: Some(1),
|
||||
uptime_ms: 12_000,
|
||||
failure: None,
|
||||
};
|
||||
let text = crate::app::view::instances::launch_toast(&finished, app.lang());
|
||||
app.state.toasts.push(ToastKind::Error, text);
|
||||
}
|
||||
Reference in new issue
Block a user