用户投诉原话:「我们的启动日志放在哪?…他找半天没找到崩溃日志」「只有一个安装日志」。 启动器运行日志(.ULL/logs/launcher.log) - presenter 构造 HostEnv 时就登记日志目录:启动早期缓冲的 200 行([probe]/[font]/[theme]) 当场刷盘,不再是「只有开过一局游戏才有日志」。 - app/** 里所有 eprintln! 诊断改走 app::diag::diag!(stderr + 文件双写,行首 [tag] 即 scope), 含 boot/boot::fallback/state/update 各线。 - boot 那一拍补一行后端事实(request/effective/fallback)。 - 滚动上限(1 MiB → launcher.1.log,只留一份)写进 README 与 docs/logs-location.md。 会话日志搬家:data/agent/sessions → logs - LauncherLayout: sessions_root()/game_logs() 新增,agent_sessions() 降级为只读兼容。 - host/logs 与 cli/commands/sessions 两个根合并(同 id 新根优先),event_path 回落旧家。 - 不搬不删;日志目录写一份 session-log-location.json 记录(moved=0, policy=read-only-compat)。 入口与文案 - 设置页「通用」新增「日志文件夹」行:路径 + 打开目录 + 复制路径(i18n 中英)。 - 日志页页头的「打开目录」不再是占位:走 M187 的 open_dir,失败文本带路径并送进剪贴板。 - README.md / README.zh-CN.md 新增「日志在哪」章节(含 crash-reports 只在游戏走到那一步才有), docs/logs-location.md 给出上限、双写判据、迁移策略与没验的部分。 守门(每条都有变异证明,见报告) - 旧家会话仍列得出/打不开 ⇒ 只读新根变红;新会话写 logs/game ⇒ 只读旧根、写回旧家都变红。 - launcher.log 滚动 ⇒ 干掉 rename 变红。 - 打开日志文件夹指向真实目录 ⇒ 换成 cache/ 或去掉 create_dir_all 都变红。 - 日志根随三模式变化 ⇒ 把 HostEnv::logs_dir 写死成便携落点变红。
75 lines
3.1 KiB
Rust
75 lines
3.1 KiB
Rust
//! Elm 三件套:`State` / `Message` / `update` + `view` 接线,以及启动序列。
|
||
//!
|
||
//! 启动序列:①探测渲染后端并写 `ICED_BACKEND`(必须在 `run()` 之前,M60 Q1)→ ②求值字体栈
|
||
//! (D28 前半)→ ③`iced::application(..).run()`(1180×760、无边框自绘标题栏)→ ④首个 `view()`
|
||
//! 打耗时;截图模式第 3 帧落盘后退出(无边框窗首帧可能是旧尺寸,M60 坑 #5)。
|
||
//!
|
||
//! ## 为什么拆成目录(M90)
|
||
//!
|
||
//! 本文件原来是**单个 400 行的 `app.rs`**:正好卡在「单文件 ≤400 行、动它前必须先拆」的硬门槛上
|
||
//! (AGENTS 的文件上限 + 本 mission 的第一条任务)。拆法与职责:
|
||
//!
|
||
//! | 文件 | 职责(**只做这一件事**) |
|
||
//! |---|---|
|
||
//! | [`state`] | [`App`] 字段 + 构造(presenter 三件在此持有)+ 主题切换 |
|
||
//! | [`message`] | [`Message`] 枚举与「导航项 → 路由」的翻译 |
|
||
//! | [`update`] | 全部 `Message` 分支 + 「用户动作 → `AppCommand`」的派发与事件回流 |
|
||
//! | [`subscription`] | 帧事件(截图)与 presenter 的 TICK 节拍 |
|
||
//! | [`view`] | `view` / `theme` / `title` |
|
||
//! | [`boot`] | [`run`]:后端探测 → 字体 → `iced::application(..)` |
|
||
//!
|
||
//! 拆分的每一步都保持**可观察行为不变**(截图四件套 `--screenshot` / `--screenshot-theme` /
|
||
//! `--screen=gallery` / `--diff` 出图逐字节相同),presenter 接线是在拆分**之后**另一步做的。
|
||
//!
|
||
//! ## 组件库为什么还在本模块下声明
|
||
//!
|
||
//! `src/lib.rs` 是五条组件线共用的文件,改它必然冲突;`#[path]` 保证物理路径仍是
|
||
//! `src/components/`(组件目录自己的归属规则不变),逻辑路径仍是 `crate::app::components`
|
||
//! (组件源码里的文档与测试都按这个路径写)。
|
||
|
||
mod appearance;
|
||
mod backend;
|
||
mod boot;
|
||
mod diag;
|
||
mod dialog;
|
||
pub(crate) mod logs_folder;
|
||
mod message;
|
||
mod state;
|
||
mod subscription;
|
||
mod update;
|
||
mod view;
|
||
mod window_alpha;
|
||
|
||
#[cfg(test)]
|
||
mod tests;
|
||
|
||
pub(crate) use boot::run;
|
||
pub use message::Message;
|
||
|
||
// 组件库(D39)在本文件声明:`src/lib.rs` 是五条组件线共用的文件,改它必然冲突;
|
||
// `#[path]` 保证物理路径仍是 `src/components/`(组件目录自己的归属规则不变)。
|
||
//
|
||
// M90:可见性从 `mod` 放到 `pub(crate) mod` —— 页面层(`src/pages/**`)要**用**真组件
|
||
// (`components::buttons` / `navigation` / `divider`),而 `app` 不是它的父模块。
|
||
// 只放开 crate 内可见,组件目录的归属规则一字不改。
|
||
#[path = "../components/mod.rs"]
|
||
pub(crate) mod components;
|
||
|
||
/// 验收窗口尺寸(1180×760 @100% DPI —— D30 的硬要求)。
|
||
pub const WINDOW_SIZE: iced::Size = iced::Size {
|
||
width: 1180.0,
|
||
height: 760.0,
|
||
};
|
||
|
||
/// 产品名(自绘标题栏的标题;`'static` 好让 view 借用)。
|
||
pub const APP_TITLE: &str = "Unlucky Launcher";
|
||
|
||
/// 窗口最小尺寸(再小骨架会挤坏:88 导航 + 页面留白 + 卡片)。
|
||
const MIN_SIZE: iced::Size = iced::Size {
|
||
width: 880.0,
|
||
height: 560.0,
|
||
};
|
||
|
||
/// 截图落盘的帧号(见模块文档)。
|
||
const CAPTURE_AT_FRAME: u32 = 3;
|