复审 p1:发布版 GUI 的「下载 JDK」页是第二处 DownloadEngine::new(要 with_progress 拿走引擎),此前只读了 gh_proxy,region / mirror_preference 到不了那里;报告却把 GUI 写成「已接」。复审 p2:CLI 四条命令同样不认这两个键 —— 同一份 launcher.json 在 GUI 与 CLI 上表现不同,等于把「设置项说假话」挪到 CLI 侧。 - app-iced downloads/engine.rs:新增 SourceSelection(只读键、不翻译)+ engine_with(.., &SourceSelection),在 gh-proxy 三态之前叠 DownloadTuning::with_source_selection(..).apply_source_selection(..) - Request 加 source_selection 字段,构造点(app/update/settings/java/downloads.rs) 用 SourceSelection::of_config(&config) 显式传值(不从缓存根反推配置路径: 反推失败会静默按 auto 收场,正是本 mission 要消灭的形状) - cli download.rs 的 tuning():链 .with_source_selection(..),四条命令共用这一处装配 - core 的 summary():把「地区 / 镜像偏好」两档印进 CLI 那行生效值(CLI 既然读了, 少印两项就是新的半真话) - shared.rs 注释说清「共享引擎」与本文件的第二处装配点;app-iced 模块头补对照表 - 新判据:JDK 下载页与 CLI 各一条断候选源顺序的用例,均配变异验证(换回裸 EngineConfig::default() / 裸 tuning 即红);补一条 region=cn + gh_proxy=off 的 叠加次序守卫(复审 P3-2) - docs/download-settings.md:§1 表格两行、§5 拆「已接 / 未接」、新增 §3.1.1 覆盖面 表、§6 补 M14-M16 三条变异、§7 补「镜像可达性没验」 连带(不加就编不过,已报备 tower):downloads/tests.rs 的 Request 字面量 +1 行、 downloads/tests/gh_proxy.rs 两处 engine_with 调用点补第四参。
124 lines
5.7 KiB
Rust
124 lines
5.7 KiB
Rust
//! 「下载一个 JDK」的 App 层落点(M197)。
|
||
//!
|
||
//! 三件事:
|
||
//!
|
||
//! | 函数 | 谁调 | 干什么 |
|
||
//! |---|---|---|
|
||
//! | [`App::start_java_download`] | `Download(major)` 消息 | 本地判据(目录/承接方/落点/是否已在跑)→ 起后台作业 |
|
||
//! | [`App::hydrate_java_downloads`] | 心跳那一拍(经 `hydrate_java_scan`) | 把作业快照灌成视图差量;**刚成功**时重扫 + 按 `java.auto_install` 决定要不要设为默认 |
|
||
//!
|
||
//! ## 为什么轮询挂在 `hydrate_java_scan` 上
|
||
//!
|
||
//! M175 的扫描已经是「后台线程 + 快照 + 心跳比对」的形状,`app/update/clock.rs` 每拍只调
|
||
//! `hydrate_java_scan()` 这一个入口。下载作业是同一族东西(后台线程 + 快照),所以复用那一拍,
|
||
//! `clock.rs` 一个字节都不用改——代价是**下载期间进度按 1 Hz 刷新**(帧时钟的判据在
|
||
//! `app/subscription.rs` 的 `needs_frames`,那是本 mission scope 之外的文件)。百分比一秒动一次
|
||
//! 对一次 100 MB 级的下载是够的;要紧的是它**会动**,而不是每秒动 60 次。
|
||
//!
|
||
//! ## 装完之后为什么要重扫
|
||
//!
|
||
//! 列表里那一行「已安装:…」来自**真扫盘的结论**(M175 的 `ScanSlot`),不是另存的安装记录。
|
||
//! 装完不重扫,界面上就会出现「下载成功」与「列表里没有它」并存——正是本仓最忌讳的那种自相矛盾。
|
||
|
||
use iced::Task;
|
||
|
||
use crate::app::message::Message;
|
||
use crate::app::state::App;
|
||
use crate::pages;
|
||
|
||
use unlucky_core::game::java::catalog;
|
||
|
||
use crate::pages::settings::java::{prefs_store, store};
|
||
|
||
impl App {
|
||
/// 下载并安装某个大版本(`Download(major)` 的落点)。
|
||
///
|
||
/// 四道本地判据,任何一道不过都在下载区顶上写清原因(点了没反应是禁止的):
|
||
/// ① 目录里有这个大版本;② 没有别的作业在跑;③ 有可写的设置文件与能解析的落点;
|
||
/// ④ 这一档在这台机器上真有一家发行版承接(纯判据,不联网)。
|
||
pub(super) fn start_java_download(&mut self, major: u32) {
|
||
use pages::settings::java::downloads::{
|
||
gh_proxy_of_config, Refusal, Request, SourceSelection,
|
||
};
|
||
|
||
self.settings.java.download_notice = None;
|
||
self.settings.java.notice = None;
|
||
self.view_dirty = true;
|
||
|
||
if catalog::find(major).is_none() {
|
||
self.settings.java.download_notice = Some(Refusal::UnknownMajor);
|
||
return;
|
||
}
|
||
if self.settings.java.downloads.busy() {
|
||
self.settings.java.download_notice = Some(Refusal::Busy);
|
||
return;
|
||
}
|
||
let Some(config) = store::config_of(&self.bridge) else {
|
||
self.settings.java.download_notice = Some(Refusal::NoStorage);
|
||
return;
|
||
};
|
||
let priority = self.settings.java.priority_vendors();
|
||
let domestic = self.settings.java.effective.domestic;
|
||
if catalog::vendors_for(major, &priority, domestic).is_empty() {
|
||
self.settings.java.download_notice = Some(Refusal::NoVendor);
|
||
return;
|
||
}
|
||
let saved_root = self.settings.java.prefs.saved_install_root.clone();
|
||
let Some(cache_root) = prefs_store::cache_root(&config) else {
|
||
self.settings.java.download_notice = Some(Refusal::NoStorage);
|
||
return;
|
||
};
|
||
let Some(install_root) = prefs_store::install_root(&config, &saved_root) else {
|
||
// 有设置文件但解析不出落点(standard 模式读不到系统目录):说这一句,
|
||
// 而不是含糊的「没有可用的设置文件」。
|
||
self.settings.java.download_notice = Some(Refusal::RootUnresolved);
|
||
return;
|
||
};
|
||
let started = self.settings.java.downloads.start(Request {
|
||
major,
|
||
cache_root,
|
||
install_root,
|
||
priority,
|
||
// `download.gh_proxy`(M197 的任务书那句「默认值可改」):空 = 跟随内置默认,
|
||
// `off` = 关,其余 = 覆盖前缀。Java 页不画这一项的 UI(归 M193 的下载设置页)。
|
||
gh_proxy: gh_proxy_of_config(&config),
|
||
// M294:`download.region` / `download.mirror_preference` 从**同一份** config 读出来
|
||
// 显式传下去(装配点不猜配置在哪;翻译在 core,这里只搬原文)。
|
||
source_selection: SourceSelection::of_config(&config),
|
||
});
|
||
if !started {
|
||
self.settings.java.download_notice = Some(Refusal::Busy);
|
||
}
|
||
}
|
||
|
||
/// 把作业快照灌成视图差量(心跳那一拍调)。返回是否变了。
|
||
pub(in crate::app) fn hydrate_java_downloads(&mut self) -> bool {
|
||
let report = self.settings.java.downloads.report();
|
||
if report == self.settings.java.download_seen {
|
||
return false;
|
||
}
|
||
let fresh = report
|
||
.success
|
||
.clone()
|
||
.filter(|success| self.settings.java.download_seen.success.as_ref() != Some(success));
|
||
self.settings.java.download_seen = report;
|
||
if let Some(success) = fresh {
|
||
// 新装上的一份:先重扫(列表要出现它),再按 `java.auto_install` 决定默认值。
|
||
let _ = self.start_java_scan();
|
||
if self.settings.java.prefs.saved_auto_install
|
||
&& self.settings.java.selected.trim().is_empty()
|
||
{
|
||
self.select_java_default(&success.binary);
|
||
}
|
||
}
|
||
self.view_dirty = true;
|
||
true
|
||
}
|
||
}
|
||
|
||
/// 消息→落点的那一层(`java.rs` 的 match 里一行转发)。
|
||
pub(super) fn on_download(app: &mut App, major: u32) -> Task<Message> {
|
||
app.start_java_download(major);
|
||
Task::none()
|
||
}
|