tower-worker
|
a0f61d8bb5
|
feat(mods): 本地 Mod 列表与启停(M224 MODTOGGLE)
三层一次做完:core 读写目录 → presenter DTO/host → 实例详情页 MODS 区。
r1 复审后 rebase 到 main 71144df(M223 已合入),并修掉四条文档疵。
core(crates/core/src/addon/mods/)
- suffix:`.disabled` / `.old` 的**唯一判据**(四态枚举 + 展示名 + 双向改名目标名),
收敛原先两份同构实现——`export/scan.rs::is_disabled_path` 与 `import/plan/paths.rs::suffix_variant`
改为委派/再导出,签名与行为不变。
- list:单根语义(入口是 derive_game_dir 派生出的运行目录)列 `<run>/mods/`,不按扩展名过滤,
符号链接/目录/怪名字逐条登记原因;`mods/` 本身是符号链接时拒(不跟随)。
- toggle:启停 = 在 `mods/` 里改名。五条守卫(裸文件名 / 目录可用 / 普通文件 / 不覆盖 / 不做
copy+delete 兜底)+ 幂等;`.disabled` 只插在 `.old` 之前。
presenter
- dto/mods:ModsCommand / ModListView / ModFailureView(不拼文案,只给结构 + OS 原文)。
- host/mods:后台线程列目录与启停,运行目录走与启动同一份 D20 派生、不写任何设置;
游戏在跑时 host 侧直接挡。
- state/mods:快照整体替换、迟到结果丢弃、在飞标记;`AppState::mods`。
app-iced(实例详情页)
- MODS 区(`pages/instances/mods.rs`):名字 + 大小 + `.old` 徽标 + Switch;运行中/在飞只读。
- 进入详情页即后台列一次(不走 3 s 观察窗,避免打红 M192 的「空闲不烧帧」守卫)。
- MODS 卡排在启动参数**之前**(详情列是滚动区,排在后面 1180×1000 下永远看不见)。
- i18n:19 条中英文案(`catalog/instances.rs` + 金表)。
rebase 冲突解法(三个文件,全是"两侧同段新增",都保留):
- `i18n/catalog/instances.rs` + `i18n/catalog/golden.rs`:M223 的 Adopt* 段在前、M224 的
InstancesMods* 段在后(= `Key::ALL` 顺序 = 金表顺序)。
- `presenter/src/state.rs`:`adopt` 与 `mods` 字段/初始化/apply_core 分支都留;`tiles()` 归
`state/tiles.rs`(本分支搬的),`apply_agent`/`agent_rail_visible` 归 `state/agent.rs`
(M223 搬的)——两处搬移不重叠,state.rs 里都不再出现。
r1 四条文档疵:
1. `pages/instances/mods.rs` 模块文档:挂载位置写反("启动参数卡之后"→实际之前),并补上为什么;
2. `state/mods.rs`:引用不存在的 `CoreEvent::ModsChanged/ModsFailed` → 改成 `CoreEvent::Mods`
+ 文字说明 Ok 落快照 / Err 落具名失败;
3. `app/state/mods_shot.rs`:文档说"目录串取真实派生结果"但代码留空 → 改成"故意留空";
4. `app/state/refresh.rs::note_mods_failure`:文档说"连点两次看见两次红字"与去重机制不符 →
改成按 `(实例, 文件, 大类)` 三元组去重(防刷屏),换文件/换实例/换大类仍会再弹。
顺带(r1 已确认的 main 红):`pages/download/options/view.rs:88-89` 两条
`clippy::doc_lazy_continuation` 只缩进修掉,文字未动。
|
2026-11-10 21:09:37 +08:00 |
|
AskaEth
|
414f6ff886
|
feat(m187): 启动失败弹窗 + 诊断包导出,并接通 DialogQueue
用户实测「MC 启动失败找不到崩溃日志」的直接修法:失败时弹一个框,把退出码、
一句人话原因、证据形态、四条真实路径与三个按钮摆在同一个地方。
- app-iced:最小一层模态(遮罩 + 卡片 + 主/次按钮 + Esc/点遮罩关闭),
消费 presenter 的 DialogQueue(此前全仓零引用,所有弹窗都画不出来);
队列管弹窗,CrashCard 管这次失败的事实,按 DialogId 绑定。
- 弹窗区分两种失败:游戏自己写了 crash-reports(贴 Description + 栈片段)/
游戏没来得及写(明说「这次没有生成崩溃报告」并贴出捕获的最后 30 行)/
什么都没抓到(给最可能原因分类)。绝不对第二种说「找不到日志」。
- 导出诊断包:core 侧新 crash_bundle 写 zip(清单 + 启动器日志 + 会话 JSONL +
crash-reports/* + hs_err + latest.log + 版本 JSON),落盘即脱敏(家目录 / token /
会话 id),单文件 4 MiB、总量 48 MiB 上限并在清单记截断。
- 启动器自身日志落盘(core::launch::launcher_log → <.ULL>/logs/launcher.log,
登记目录前先缓冲),补上「双击启动时诊断行直接蒸发」的缺口。
- i18n:25 条中英文案进 catalog/logs.rs + 金表。
- 取证:ULL_DIALOG_FIXTURE=crash-report|no-logs|export 在临时目录造真文件出图,
wgpu 与 tiny-skia 各一套,见 DevDocs/artifacts/m187/。
未复现 M190 的「owned 文字在 wgpu 下丢字」:同一串中文两条文字路径、两种后端逐字相同
(ab-wgpu.png / ab-tinyskia.png),因此本轮未改任何渲染路径。
|
2026-11-08 22:42:00 +08:00 |
|
AskaEth
|
03741ecd2d
|
fix(m161): 收更新键/按钮/矮窗口/启动错误/导入结果五笔债
① update.auto_check / update.channel 登记进 core setting schema(1.6.0)
- 新增 setting/keys/update.rs(两键 + UPDATE_CHANNELS,只允许 stable);
SettingSchema 加 with_all 供域键表批量登记。
- 新增 setting/update_prefs.rs:cache/update/prefs.json → launcher.json 的一次性迁移。
四条硬约束:源指纹闸门(幂等)、不丢 false、新值胜出、旧文件改名 .migrated 后不再被读;
主配置不可写时不动旧文件。收据 config/update-prefs-migration.json。
- presenter Runtime 建会话时迁一次并把结局留在 migration();prefs 字段换成
auto_check + 每次派发从主配置读 channel(不再硬编码 Channel::Stable)。
保留旧字段 auto_check 的真实来源(原有测试 cases 会断言)。
- CLI config get/set/dump 先跑同一次迁移(幂等),输出里给 migration 段与收据路径。
② presenter/dto/events.rs 的「本次会话不再弹提示条」注释改成真实语义
(记的是版本号:同版本压住、更高版本照弹、手动检查清掉)。
③ 检查/下载进行中按钮禁用:pages/update/busy.rs 的 busy/can_check/can_apply;
设置页两颗按钮改画禁用(不是消失),app 层 on_update_action 再挡一道
(忙碌时 CheckNow/Apply 不派发);新增两条用例(含「忙完恢回可点」)。
④ 内容库低高度:content_layout::MIN_BODY_HEIGHT=460 + BodyMode(按固定件+三整行算出来,
用例守着算式);frame::body_height 从 Ui::metrics 算正文可用高,pages::Model 带 window_height。
≥460 列表自己滚;<460 主列整列一个滚动条、列表按自然高度铺开。
⑤ 启动错误文案本地化:presenter 删掉 launch_summary / 「启动失败:」前缀 / 五条中文阶段前缀,
改发 LaunchFailureView{stage,detail};LaunchFinished 改带 exit_code/uptime_ms/failure,
Toast 由 app 层按 i18n key 现求(与 install_cancelled 同构)。InstancesFailed 拆成
InstancesFailedStage(列表单行)+ LaunchStageFailed(详情/Toast 全文)。
⑥ 导入结果块:ImportReportView 加 failure_stage(NotStarted/RolledBack/RollbackIncomplete,
由 core 的 rollback 机器位推出);标题、图标、底色三处分档,预检失败不再说「已回滚」。
顺带:六处注释/文档漂移(update.rs 的分工表与偏好落点、pack 的「已整包回滚」、
build_request 的 Errors、settings/update 的按钮禁用说明等),
以及为守 400 行把 update/cli-config/core-keys/presenter-dto/presenter-launch/i18n-golden
里贴线或越线的文件按模块拆开(纯搬移,行为不变)。
|
2026-11-07 15:02:13 +08:00 |
|
AskaEth
|
e2021645d7
|
feat(launch): M157 实例级启动参数(五项回落 + graphicsBackend 三态)
core: 新增 game/launch_overrides(LaunchOverrides 五项 All-Option + 三级回落 + 文本补丁校验)与 launch/overrides(拼装落位:全局 java.extra_args 进 user.jvm、实例 jvmArgs 进 override_jvm、gameArgs 进 user.game、memory 进 -Xmx、backend 进 --graphicsBackend 并复用既有版本门槛告警);实例 schema 登记 launch.* 五键。
presenter: dto/LaunchArgsView+LaunchArgsPatch,主机侧读/写与门槛判定(backend_allowed),AppCommand::SetInstanceLaunchArgs。
cli: 新命令 instances launch-args(读/写/--clear),launch 装配链消费回落值。
app-iced: 实例详情页「启动参数」区(JVM/游戏参数、内存、Java、三态后端 chips + 灰化提示 + 保存/恢复),表单状态归 App、i18n 中英文案同步。
|
2026-11-07 10:36:35 +08:00 |
|
AskaEth
|
d4fd675935
|
feat(app-iced): M119 把 presenter 的 agent 四契约与账户窄入口接进 iced 壳
M103 把 AI 会话的投影(`AgentRail` + `submit/mark_read/confirm`)做完了,M114 把账户三轨做完,
但 iced 壳一直没接:M103 复审确认 `Presenter::` 零非测试消费者,M104 的右栏会话数据来自内置样本。
这一个提交就是那一步——**右栏与账户页吃 presenter 的真实状态**。
## 接线层(新增 `crates/app-iced/src/presenter/`)
| 文件 | 是什么 |
|---|---|
| `agent.rs` | `AgentHost`:presenter 句柄(四契约)+ 事件队列 + **具名**失败(`AgentFailure`:`unreachable` / `not_implemented`)|
| `transport.rs` | `AgentTransport` 的 iced 侧实现(脚本化 rig + 五种剧情 + 两种失败注入)|
| `rig.rs`(仅测试) | 账户轨的 `Backend`:`AppCommand` → host 形状的 `CoreEvent` |
| `mod.rs` | 逻辑路径说明 + **线程/通道边界** |
物理目录 `src/presenter/`,逻辑名字 `crate::app::state::presenter`——由 `app/state.rs` 用
`#[path]` 挂载(与 `shell::agent` 挂 `pages/agent/` 同一个先例:scope 不含 `lib.rs`)。
## 事件回流
`transport` 只**入队**、UI 只**出队**:`advance`→`pump` 里同拍抽干,抽出来的这批经
**既有 `Message::Agent(..)` 通道**(新变体 `Events(Vec<AppEvent>)`)回到 `on_agent`,再由
`Presenter::apply` 落地。同一条漏斗,所以用户点击与后端事件不会各改一次状态。
## 会话内容只留一份
`AgentUi` 里的 `transcript/busy/unread` **删掉**,右栏与独立页直接读 `agent_rail()`
(`pages/agent::spec` 零拷贝借)。M104 的样本会话(`demo::transcript()`)一并删除:出厂就是
空会话,取证夹具要内容就**跑一轮真提交**(`ULL_AGENT_FIXTURE=turn`),消息只能由 presenter 产生。
## 视图
- 气泡按 `ChatMessage.role` 画(User/Assistant/Tool/System),没有任何壳自己的会话类型;
- 新增两条横幅(`conversation/banners.rs`):**失败态**(catalog 标题 + 已脱敏正文)与
**写操作确认**(摘要 + Allow/Deny → `agent_confirm`);
- 拖动缝与折叠条按 400 行硬线拆到 `mod.rs` 之外(`strip.rs`、`conversation/{transcript,banners}.rs`)。
## 未读口径
presenter 判「栏可见吗」用的是它自己的 router + `prefs.ai_collapsed`,而这两件的真源在 `App`。
`refresh_view` 用 presenter 的两个**窄入口**(`navigate` / `prefs_mut().ai_collapsed`)单点写回,
带幂等闸(相同就不重复写,避免 `navigate(Route::Agent)` 顺手 mark_read 吃掉用户攒的未读)。
## 账户页
账户列表与登录事件仍走 `AppCommand`/`CoreEvent`(M114 的形状没动),本轮把**登录指令与
列表消费**纳入同一套树测试:添加离线档案 → 列表出现 → 切换 → 删除;设备码「进行中可见 + 可取消」;
失败态(名字不合法 / 凭据失效)都给具名错误。
## 树测试(9 条,`cargo test -p unlucky-app-iced --lib` 全绿:599 passed / 0 failed)
- `app/update/agent/tests.rs`:提交 → 事件回流 → 右栏出现该轮 + `busy` 翻转 + 标记已读归零;
确认条可裁决且记审计;三种失败各给具名横幅;草稿逐字同步。
- `app/update/account/tests.rs`:增/切/删端到端;设备码进行中与取消;两种失败态;
M114 的三条回归闸(原内联测试搬出来)。
- `pages/agent/tests.rs`:视图契约(`spec` 原样借 rail)、a11y 标签、焦点环、两种宿主全态构图。
顺带:`app/tests.rs` 里三条 `agent.unread` 断言跟着 rail 走(出厂 0 未读),`view/account_page.rs`
的 `docked` 调用点补上 rail 与失败横幅。
|
2026-11-05 08:02:58 +08:00 |
|
AskaEth
|
3c61a2397e
|
refactor(app-iced): 拆 state.rs(400 行) 与 update.rs(399 行) 为功能子文件
两个文件都贴着 400 行硬线、零余量,M119 要往里加字段与一行 drain。**这一个提交只搬不改**
(下一次提交才是改动),搬的位置按功能切:
| 原位置 | 现在 | 内容 |
|---|---|---|
| `app/state.rs` | `state.rs`(172) | 只剩 crate 文档 + 常量 + `struct App` 的字段与注释 |
| 同上 | `state/construct.rs` | 两个构造器 + 字段初始化表 |
| 同上 | `state/refresh.rs` | `refresh_view`(快照 → 视图模型的唯一转换点) |
| 同上 | `state/theme.rs` | `Ui` 重算 / 主题档 / `has_screenshot` / `ui()` |
| `app/update.rs` | `update/clock.rs` | 推进一拍 / 派发 / 抽干事件 / 自动选中 |
一处**非字面**的改动:搬进子模块之后 `pub(super)` 的语义从「crate::app」变成「crate::app::state」,
所以这些方法改成 `pub(in crate::app)`——可见范围与搬家前逐字相同,只是写法得跟着模块路径走。
除此之外照抄原文(含原有注释与文档)。
搬完 `cargo check -p unlucky-app-iced --all-targets` 零 error 零 warning。
|
2026-11-05 08:02:45 +08:00 |
|