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
里贴线或越线的文件按模块拆开(纯搬移,行为不变)。
This commit is contained in:
1 parent
b2d9f3927f
commit
03741ecd2d
69 files changed
+2653
-707
No files matched your search
@@ -14,8 +14,8 @@
|
||||
|
||||
use unlucky_i18n::{Catalog, Key};
|
||||
use unlucky_presenter::dto::{
|
||||
ConflictChoiceView, ConflictFileView, ConflictReasonView, ImportErrorView, ImportReportView,
|
||||
ImportStatusView, MissingFileView, MissingReasonView,
|
||||
ConflictChoiceView, ConflictFileView, ConflictReasonView, ImportErrorView,
|
||||
ImportFailureStageView, ImportReportView, ImportStatusView, MissingFileView, MissingReasonView,
|
||||
};
|
||||
|
||||
use super::PackPageState;
|
||||
@@ -48,10 +48,40 @@ pub struct ConflictRow {
|
||||
pub expanded: bool,
|
||||
}
|
||||
|
||||
/// 致命失败块(**已整包回滚**)。
|
||||
/// 致命失败块(**两种措辞,不共用**)。
|
||||
///
|
||||
/// 为什么不是一句「失败」:`NotStarted`(预检就没过,一个字节都没写)与 `RolledBack`
|
||||
/// (写进去了,又整包回滚干净)对用户是不同的消息——前者「去修包再试」,后者「刚才动过你的目录,
|
||||
/// 已经复原」。M161 之前两者共用一句「已回滚 —— 目标目录零残留」,预检失败时那句话是假的。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum FatalKind {
|
||||
/// 预检/装配阶段失败:目标目录**一个字节都没写**
|
||||
NotStarted,
|
||||
/// 写过目标目录,回滚**完整**完成
|
||||
RolledBack,
|
||||
/// 写过,但回滚有失败项(目标目录可能与导入前不同)
|
||||
RollbackIncomplete,
|
||||
}
|
||||
|
||||
impl FatalKind {
|
||||
/// 图标(与 [`Fatal::title`] 各说一遍:颜色/图标关掉时标题仍然分得清)。
|
||||
#[must_use]
|
||||
pub const fn icon(self) -> unlucky_design::icons::IconKind {
|
||||
match self {
|
||||
// 预检没过 = 「还没开始」,用警示而不是「已出错」:目录是干净的
|
||||
Self::NotStarted => unlucky_design::icons::IconKind::Warn,
|
||||
Self::RolledBack => unlucky_design::icons::IconKind::Restore,
|
||||
Self::RollbackIncomplete => unlucky_design::icons::IconKind::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 致命失败块。
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Fatal {
|
||||
/// 「已回滚 —— 目标目录零残留」
|
||||
/// 三种阶段之一(决定标题/图标/底色)
|
||||
pub kind: FatalKind,
|
||||
/// 标题(预检未通过 / 已回滚 / 回滚不完整)
|
||||
pub title: String,
|
||||
/// 大类名(`路径穿越` / `清单损坏` …)
|
||||
pub label: String,
|
||||
@@ -124,7 +154,7 @@ pub(super) fn report_of(
|
||||
|
||||
Report {
|
||||
status: report.status,
|
||||
title: status_title(report.status, catalog).to_owned(),
|
||||
title: status_title(report, catalog).to_owned(),
|
||||
subtitle: subtitle(report, catalog),
|
||||
written_line: catalog.render(
|
||||
Key::PackReportWritten,
|
||||
@@ -133,7 +163,10 @@ pub(super) fn report_of(
|
||||
("bytes", &human(report)),
|
||||
],
|
||||
),
|
||||
fatal: report.error.as_ref().map(|error| fatal_of(error, catalog)),
|
||||
fatal: report
|
||||
.error
|
||||
.as_ref()
|
||||
.map(|error| fatal_of(error, report.failure_stage, catalog)),
|
||||
missing_title,
|
||||
missing: report
|
||||
.missing
|
||||
@@ -177,11 +210,22 @@ fn human(report: &ImportReportView) -> String {
|
||||
unlucky_presenter::dto::human_bytes(report.bytes_written)
|
||||
}
|
||||
|
||||
fn status_title(status: ImportStatusView, catalog: Catalog) -> &'static str {
|
||||
match status {
|
||||
/// 标题:三态 + **失败阶段**(预检未通过 ≠ 已回滚,M161)。
|
||||
fn status_title(report: &ImportReportView, catalog: Catalog) -> &'static str {
|
||||
match report.status {
|
||||
ImportStatusView::Success => catalog.text(Key::PackStatusSuccess),
|
||||
ImportStatusView::Partial => catalog.text(Key::PackStatusPartial),
|
||||
ImportStatusView::Failed => catalog.text(Key::PackStatusFailed),
|
||||
ImportStatusView::Failed => match report.failure_stage {
|
||||
Some(ImportFailureStageView::NotStarted) => {
|
||||
catalog.text(Key::PackStatusFailedNotStarted)
|
||||
}
|
||||
Some(ImportFailureStageView::RollbackIncomplete) => {
|
||||
catalog.text(Key::PackStatusFailedIncomplete)
|
||||
}
|
||||
// `None` 不该出现(失败必有阶段);退回「已回滚」这一句是旧行为,
|
||||
// 只有拿不到阶段时才会走到(例如未来的旧版对端)。
|
||||
_ => catalog.text(Key::PackStatusFailed),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,9 +247,24 @@ fn subtitle(report: &ImportReportView, catalog: Catalog) -> String {
|
||||
parts.join(" · ")
|
||||
}
|
||||
|
||||
fn fatal_of(error: &ImportErrorView, catalog: Catalog) -> Fatal {
|
||||
fn fatal_of(
|
||||
error: &ImportErrorView,
|
||||
stage: Option<ImportFailureStageView>,
|
||||
catalog: Catalog,
|
||||
) -> Fatal {
|
||||
let kind = match stage {
|
||||
Some(ImportFailureStageView::NotStarted) => FatalKind::NotStarted,
|
||||
Some(ImportFailureStageView::RollbackIncomplete) => FatalKind::RollbackIncomplete,
|
||||
_ => FatalKind::RolledBack,
|
||||
};
|
||||
let title = match kind {
|
||||
FatalKind::NotStarted => catalog.text(Key::PackFatalTitleNotStarted),
|
||||
FatalKind::RolledBack => catalog.text(Key::PackFatalTitle),
|
||||
FatalKind::RollbackIncomplete => catalog.text(Key::PackFatalTitleIncomplete),
|
||||
};
|
||||
Fatal {
|
||||
title: catalog.text(Key::PackFatalTitle).to_owned(),
|
||||
kind,
|
||||
title: title.to_owned(),
|
||||
label: error.label.clone(),
|
||||
message: error.message.clone(),
|
||||
code: error.code.clone(),
|
||||
|
||||
Reference in new issue
Block a user