feat(m159): 自更新 GUI 客户端接线 + CLI update check/apply 同一内核
D50 的「检查 → 提示 → 可拒绝 → 下载校验 → 下一次启动生效」整环接线,GUI 与
CLI 共用 core 的一条内核(`update::Job`),并顺带修掉 M157 最后一轮复审的三处 P3。
内核(core::update)
- 新增 job.rs:`Job { source, target, staging, dest }` + `check` / `apply`(复查 →
取包 → 长度/SHA256 双检 → 原子替换),`default_source`(GitHub,`ULL_UPDATE_DIR`
可切本地目录夹具)、`process_dest`、`staging_dir`。
- `mod.rs` 导出 job 一族;`source.rs` 为 `Box<dyn UpdateSource>` 补 trait 转发
(壳层要运行期选源,`UpdateChecker` 是泛型的)。
presenter(宿主通道)
- `dto/update.rs`:`UpdateView` / `UpdateOutcome`(Idle/Checking/UpToDate/Available/
MissingArtifact/Failed 六态,**失败与最新不折叠**)/ `UpdateBanner` 优先级判据。
- `host/update.rs`:Factory(生产 GitHub / 单测本地目录)+ core 结论 → DTO 的唯一映射
+ 更新域偏好(`cache/update/prefs.json`)。
- `host/update_state.rs`:Runtime(会话状态机:begin_check/adopt/begin_apply/dismiss/
set_auto_check)+ `CoreHost` 派发与后台线程。
- `AppCommand::{CheckUpdate, ApplyUpdate, DismissUpdate, SetUpdateAutoCheck}`、
`CoreEvent::Update`、`AppState.update`;`refresh_all` 按开关派发静默检查。
app-iced
- 设置页新增第 5 组「更新」(当前版本 / 渠道 / 自动检查开关 / 立即检查 / 上次检查与
结果 / 下载并安装 / 就位后立即重启),走 `settings::view` 的 `update` 形参 + 按下标
分发(与 M106 语言行同一取舍)。
- 顶部提示条(每页可见):有新版本(版本号 + 体积 + 说明摘要,可安装/可忽略)、下载中、
已就位(立即重启);静默检查失败**不**弹条(原因进设置页)。
- `pages::Message::Update(UpdateAction)` → `app/update/update_action.rs`;「立即重启」
拉同参数的新进程后退出(截图通道不重启)。
CLI
- `ull update check` / `ull update apply [--dest <path>]`:复用同一 `Job`;四种结论分开
报(`--json` 的 `status`),失败退出码 1(`update_check_failed` / `update_apply_failed`)。
i18n
- 新增 `catalog/update.rs`(30 条,链尾追加)+ 金表对应 30 行。
M157 复审 P3 三件
- `app/update/instances.rs` 模块文档改成「清脏的唯一时机是回程快照等于表单」。
- `pages/instances/demo.rs` 的 `demo_form` 注释改成现状(两个参数框早已是单行输入)。
- `pages/instances/launch_args.rs`:门限不满足时只灰 `opengl`/`vulkan`,`default` 仍可点
(它是「不下发」的安全档);判据抽成 `backend_chip_enabled` 并补 3 条用例。浅色 + 灰化
两张图:`C:/Temp/m159-shots/instances-launch-args-{light,gated}.png`。
顺带:harness 支持 `ULL_SETTINGS_GROUP=<下标>`(拍第 5 组的验收图需要它)。
验证:cargo fmt --check 绿;cargo clippy --workspace --all-targets -D warnings 绿;
cargo test --workspace --all-targets 51 个测试二进制全绿(唯一例外:core::addon::pack
一族要造 4 GiB 稀疏文件,本机磁盘 99% 满 ⇒ StorageFull,与本次改动无关);CLI 用本地
目录夹具跑通「发现 9.9.9 → 下载 → 校验 → 替换运行中的 exe → 备份留旧文件」,并验证
摘要不符时拒绝应用、目标文件零改动、暂存目录零残留。
This commit is contained in:
1 parent
a80362915a
commit
1c8f6aa1b3
44 files changed
+3341
-22
No files matched your search
@@ -125,6 +125,7 @@ mod loader;
|
||||
mod logs;
|
||||
mod nav;
|
||||
mod settings;
|
||||
mod update;
|
||||
|
||||
/// 拆分前的 `key -> (en, zh-CN)` **逐字快照**(金表)。
|
||||
///
|
||||
@@ -195,6 +196,7 @@ use settings::{
|
||||
settings_ai_entries, settings_appearance_entries, settings_download_entries,
|
||||
settings_general_entries, settings_java_entries,
|
||||
};
|
||||
use update::update_entries;
|
||||
|
||||
// 装配顺序 = `Key` 的声明顺序。**与拆分前逐条一致**,动它等于动 `Key` 的 `Ord` 与导出表顺序,
|
||||
// 金表(`catalog/golden.rs`)会红。设置页那五个域按页面上的分组顺序排,中间三个现在是空的。
|
||||
@@ -224,6 +226,8 @@ nav_entries! {
|
||||
// M114:账户页。同理**追加在 main 已占住的链尾之后**(先 content 再 account),
|
||||
// 金表只追加不重排。
|
||||
account_entries,
|
||||
// M159:自更新(设置页「更新」分组 + 顶部提示条)。同样只追加在链尾之后。
|
||||
update_entries,
|
||||
finish,
|
||||
{}
|
||||
}
|
||||
|
||||
@@ -361,4 +361,34 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
|
||||
("AccountNoticeTitleDone", "Account updated", "账户已更新"),
|
||||
("AccountHintAuthlibReauth", "Enter the password again for {server}.", "请输入 {server} 的密码。"),
|
||||
("AccountHintOfflineNoRelogin", "Local profiles have no server account to sign in again — create a new profile instead.", "本地档案没有可重新登录的服务器账户,请新建一个档案。"),
|
||||
("SettingsGroupUpdate", "Updates", "更新"),
|
||||
("SettingsUpdateCurrent", "Current version", "当前版本"),
|
||||
("SettingsUpdateChannel", "Channel", "更新渠道"),
|
||||
("SettingsUpdateChannelStable", "Stable", "稳定版"),
|
||||
("SettingsUpdateAutoCheck", "Check for updates on startup", "启动时检查更新"),
|
||||
("SettingsUpdateCheckNow", "Check now", "立即检查"),
|
||||
("SettingsUpdateChecking", "Checking…", "正在检查…"),
|
||||
("SettingsUpdateNever", "Not checked yet", "还没检查过"),
|
||||
("SettingsUpdateUpToDate", "You are on the latest version ({version})", "已是最新({version})"),
|
||||
("SettingsUpdateAvailable", "Version {version} is available ({size})", "有新版本 {version}({size})"),
|
||||
("SettingsUpdateMissingArtifact", "Version {version} is out, but there is no build for this platform yet.", "{version} 已发布,但还没有本平台的安装包。"),
|
||||
("SettingsUpdateFailed", "Check failed: {reason}", "检查失败:{reason}"),
|
||||
("SettingsUpdateApply", "Download and install", "下载并安装"),
|
||||
("SettingsUpdateApplying", "Downloading and verifying…", "正在下载并校验…"),
|
||||
("SettingsUpdateReady", "Version {version} is ready — restart to use it.", "版本 {version} 已就位,重启后生效。"),
|
||||
("SettingsUpdateNotes", "Release notes: {notes}", "更新说明:{notes}"),
|
||||
("SettingsUpdateForced", "This update is required", "这是一次强制更新"),
|
||||
("SettingsUpdateLastChecked", "Last check", "上次检查"),
|
||||
("SettingsUpdateHint", "Downloads are verified with SHA256 before they touch the launcher. The running copy stays as it is until you restart.", "更新包在落到启动器之前会做 SHA256 校验;正在运行的这一份在你重启之前不会变。"),
|
||||
("UpdateBannerTitleAvailable", "Version {version} is available", "发现新版本 {version}"),
|
||||
("UpdateBannerBodyAvailable", "Download size {size}", "下载体积 {size}"),
|
||||
("UpdateBannerTitleReady", "Update ready", "更新已就位"),
|
||||
("UpdateBannerBodyReady", "Version {version} will run after a restart.", "重启后运行版本 {version}。"),
|
||||
("UpdateBannerTitleFailed", "Update failed", "更新失败"),
|
||||
("UpdateBannerApplying", "Downloading the update…", "正在下载更新…"),
|
||||
("UpdateBannerInstall", "Download and install", "下载并安装"),
|
||||
("UpdateBannerDismiss", "Skip this version", "忽略这个版本"),
|
||||
("UpdateBannerRestartNow", "Restart now", "立即重启"),
|
||||
("UpdateBannerRestartLater", "Not now", "稍后"),
|
||||
("UpdateBannerRetry", "Try again", "重试"),
|
||||
];
|
||||
@@ -0,0 +1,60 @@
|
||||
//! 自更新文案(M159):设置页「更新」分组 + 顶部提示条。
|
||||
//!
|
||||
//! 域文件的形状见 [`crate::catalog`] 的「域装配」一节;本域**追加在链尾**(`account_entries`
|
||||
//! 之后),于是 `Key::ALL` 顺序 = 金表顺序 = 先 main 的全部域,最后 update(金表只追加不重排)。
|
||||
//!
|
||||
//! 三条口径:
|
||||
//!
|
||||
//! 1. **「检查失败」与「已是最新」是两句不同的文案**(mission 的硬要求):前者带原因,
|
||||
//! 后者带版本号。别为了少一个 key 把它们合并成一条;
|
||||
//! 2. 体积走 `{size}`(由页面按 `human_bytes` 格式化后传入),版本号走 `{version}`——
|
||||
//! 目录里不写死任何版本号;
|
||||
//! 3. 品牌/技术名词不翻:`OpenGL` / `SHA256` / `GitHub` 这类保持原样。
|
||||
|
||||
macro_rules! update_entries {
|
||||
($next:ident, $($rest:ident,)* { $($acc:tt)* }) => {
|
||||
$next! { $($rest,)* {
|
||||
$($acc)*
|
||||
// ── 设置页「更新」分组
|
||||
SettingsGroupUpdate => ("Updates", "更新"),
|
||||
SettingsUpdateCurrent => ("Current version", "当前版本"),
|
||||
SettingsUpdateChannel => ("Channel", "更新渠道"),
|
||||
SettingsUpdateChannelStable => ("Stable", "稳定版"),
|
||||
SettingsUpdateAutoCheck => ("Check for updates on startup", "启动时检查更新"),
|
||||
SettingsUpdateCheckNow => ("Check now", "立即检查"),
|
||||
SettingsUpdateChecking => ("Checking…", "正在检查…"),
|
||||
SettingsUpdateNever => ("Not checked yet", "还没检查过"),
|
||||
SettingsUpdateUpToDate => ("You are on the latest version ({version})", "已是最新({version})"),
|
||||
SettingsUpdateAvailable => ("Version {version} is available ({size})", "有新版本 {version}({size})"),
|
||||
SettingsUpdateMissingArtifact => (
|
||||
"Version {version} is out, but there is no build for this platform yet.",
|
||||
"{version} 已发布,但还没有本平台的安装包。"
|
||||
),
|
||||
SettingsUpdateFailed => ("Check failed: {reason}", "检查失败:{reason}"),
|
||||
SettingsUpdateApply => ("Download and install", "下载并安装"),
|
||||
SettingsUpdateApplying => ("Downloading and verifying…", "正在下载并校验…"),
|
||||
SettingsUpdateReady => ("Version {version} is ready — restart to use it.", "版本 {version} 已就位,重启后生效。"),
|
||||
SettingsUpdateNotes => ("Release notes: {notes}", "更新说明:{notes}"),
|
||||
SettingsUpdateForced => ("This update is required", "这是一次强制更新"),
|
||||
SettingsUpdateLastChecked => ("Last check", "上次检查"),
|
||||
SettingsUpdateHint => (
|
||||
"Downloads are verified with SHA256 before they touch the launcher. The running copy stays as it is until you restart.",
|
||||
"更新包在落到启动器之前会做 SHA256 校验;正在运行的这一份在你重启之前不会变。"
|
||||
),
|
||||
// ── 顶部提示条
|
||||
UpdateBannerTitleAvailable => ("Version {version} is available", "发现新版本 {version}"),
|
||||
UpdateBannerBodyAvailable => ("Download size {size}", "下载体积 {size}"),
|
||||
UpdateBannerTitleReady => ("Update ready", "更新已就位"),
|
||||
UpdateBannerBodyReady => ("Version {version} will run after a restart.", "重启后运行版本 {version}。"),
|
||||
UpdateBannerTitleFailed => ("Update failed", "更新失败"),
|
||||
UpdateBannerApplying => ("Downloading the update…", "正在下载更新…"),
|
||||
UpdateBannerInstall => ("Download and install", "下载并安装"),
|
||||
UpdateBannerDismiss => ("Skip this version", "忽略这个版本"),
|
||||
UpdateBannerRestartNow => ("Restart now", "立即重启"),
|
||||
UpdateBannerRestartLater => ("Not now", "稍后"),
|
||||
UpdateBannerRetry => ("Try again", "重试"),
|
||||
} }
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use update_entries;
|
||||
Reference in new issue
Block a user