用户原话:「我们内置了那么多镜像源 甚至用户不能手动选择指定版本下载。」
「自动下载 jdk17 作为基准版本,后续在设置中提供多版本可供用户下载。」
- core:新增 `game::java::catalog`(8/11/17/21/25 五档 × 能承接的发行版 × 「该装哪档」),
数据全部来自 `JdkVendor::supports` 与 `vendor::order`,不复制第二份真相。
- progress:`SourceFailed` 补一个结构化的 `kind`(在这之前只有中文 `reason`,双语界面
要么放弃语言、要么放弃「哪个源为什么退避」这条用户可见信息)。
- app-iced:`downloads` 模块真下(后台线程 + `ProgressEmitter` + 快照),三态(选择列表 /
下载中 / 失败)都能说出「命中的源 / 退避原因 / 试过哪些源」;成功后重扫并(在
`java.auto_install` 开着且没有默认 JDK 时)把新装的那份设为默认。
- 三个设置键做成可改 UI:`java.installRoot` / `java.vendorPriority` / `java.auto_install`,
各自带「现在生效什么、从哪一层来」(数据目录模式 / 地区默认序),改完回读落盘值。
- `State::satisfied` 换成带方向的 `Fit`:1.12.2 + Java 21 不再被说成「低于要求」。
- i18n:删掉 `SettingsJavaEmptyBody` / `SettingsJavaAddHint` 的 markdown 反引号;
`SettingsJavaNeverScannedBody` 改成不与首屏自动扫矛盾的表述。
- 出图三张(选择列表 / 下载中 / 失败)在 DevDocs/artifacts/m197/。
顺带拆文件守 400 行:`golden/tail.rs` 的 M174 段搬到 `golden/tail_ai.rs`,
`pages/settings/java/{context,prefs,prefs_store,downloads,download_view}` 各自成模块。
182 lines
7.6 KiB
Rust
182 lines
7.6 KiB
Rust
//! 「Java」分组的截图种子(M175,`ULL_JAVA_STATE`):**只给 `--screenshot` 用**。
|
||
//!
|
||
//! 三档对应任务书要的三张图:未安装 Java 的空态 / 检测到两个 JDK 并选中其一 / 内存与 JVM 参数
|
||
//! 的编辑态。编辑态只让**内存**越界(`validate()` 一次只报第一个错,所以图上看到的是「内存超出
|
||
//! 允许范围」+ 内存框标红;引号那条另有单测,不靠这张图证明)。
|
||
//!
|
||
//! M197 加了三档,对应「下载一个 JDK」的三态(任务书要的三张图):`download`(版本选择列表)/
|
||
//! `downloading`(下载中:百分比 + 当前源 + 一次退避)/ `download-failed`(失败:最后试到的源)。
|
||
//! 三档都把三个设置键摆成生产上真会出现的值(自定义落点 + 自己排的发行版顺序 + 自动准备开着),
|
||
//! 于是一张图里能同时看到「版本目录」与「三个键」。
|
||
//!
|
||
//! 与 `ULL_AI_STATE` / `ULL_UPDATE_STATE` / `ULL_FONT_STATUS` 同一族取证开关:只影响这一次进程,
|
||
//! 产品路径不设它。种子里的路径是**写死的示例路径**(真实机器上没有),所以它只在出图通道里出现;
|
||
//! 产品路径的真值一律来自 `core::game::java::staged` 的真扫盘。
|
||
|
||
use super::state::{Context, Layer, Notice, Refusal, Requirement, RuntimeRow, State};
|
||
|
||
/// 取证开关 `ULL_JAVA_STATE`(只给 `--screenshot` 用)。
|
||
///
|
||
/// 三档对应三张图:`empty`(未检测到)/ `two`(两个 JDK 并选中其一)/ `editing`(改了内存与
|
||
/// JVM 参数、还没保存)。与 `ULL_AI_STATE` / `ULL_UPDATE_STATE` 同一族,只影响这一次进程。
|
||
#[must_use]
|
||
pub fn build(raw: &str) -> Option<State> {
|
||
let mut state = State {
|
||
storage: true,
|
||
scanned: true,
|
||
..State::default()
|
||
};
|
||
match raw.trim() {
|
||
"empty" => {
|
||
state.memory = "2048".to_string();
|
||
state.saved_memory = 2048;
|
||
}
|
||
"two" => {
|
||
state.runtimes = vec![
|
||
RuntimeRow {
|
||
binary: "C:/Program Files/Eclipse Adoptium/jdk-17.0.13/bin/java.exe"
|
||
.to_string(),
|
||
version: "openjdk version \"17.0.13\" 2024-10-15".to_string(),
|
||
major: Some(17),
|
||
vendor: Some("Temurin".to_string()),
|
||
source: "system",
|
||
},
|
||
RuntimeRow {
|
||
binary: "C:/Program Files/Microsoft/jdk-21.0.4/bin/java.exe".to_string(),
|
||
version: "openjdk version \"21.0.4\" 2024-07-16 LTS".to_string(),
|
||
major: Some(21),
|
||
vendor: Some("Microsoft".to_string()),
|
||
source: "system",
|
||
},
|
||
];
|
||
state.selected = state.runtimes[1].binary.clone();
|
||
state.manual = vec!["D:/jdk/zulu-21".to_string()];
|
||
state.memory = "4096".to_string();
|
||
state.saved_memory = 4096;
|
||
state.jvm = "-XX:+UseG1GC".to_string();
|
||
state.saved_jvm = "-XX:+UseG1GC".to_string();
|
||
state.context = Context {
|
||
required: Some(Requirement {
|
||
instance: "生存服".to_string(),
|
||
version: "1.20.1".to_string(),
|
||
minimum: 17,
|
||
maximum: None,
|
||
}),
|
||
layer: Some(Layer::Global),
|
||
effective_memory_mb: Some(4096),
|
||
};
|
||
}
|
||
"editing" => {
|
||
let mut seeded = build("two")?;
|
||
seeded.memory = "128".to_string();
|
||
seeded.jvm = "-XX:+UseG1GC -Xss\"512k".to_string();
|
||
seeded.dirty = true;
|
||
seeded.notice = Some(Notice::Refused(Refusal::MemoryRange));
|
||
return Some(seeded);
|
||
}
|
||
// ── M197:「下载一个 JDK」的三态
|
||
"download" => {
|
||
let mut seeded = build("two")?;
|
||
seeded.context = download_context(21);
|
||
seeded.prefs = seeded_prefs();
|
||
seeded.effective = seeded_effective();
|
||
return Some(seeded);
|
||
}
|
||
"downloading" => {
|
||
let seeded = build("download")?;
|
||
seeded.downloads.seed_report(super::downloads::Report {
|
||
job: Some(super::downloads::Job {
|
||
major: 21,
|
||
phase: super::downloads::Phase::Downloading,
|
||
downloaded: 96_468_992,
|
||
total: Some(210_763_776),
|
||
source: Some("tuna".to_string()),
|
||
last: Some(super::downloads::Event::Retry {
|
||
source: "tuna".to_string(),
|
||
kind: unlucky_core::download::DownloadErrorKind::ServerError,
|
||
attempt: 2,
|
||
retry_in_ms: 2_000,
|
||
}),
|
||
}),
|
||
tries: vec![super::downloads::Try {
|
||
source: "tuna".to_string(),
|
||
kind: unlucky_core::download::DownloadErrorKind::ServerError,
|
||
}],
|
||
failure: None,
|
||
success: None,
|
||
});
|
||
return Some(seeded);
|
||
}
|
||
"download-failed" => {
|
||
let seeded = build("download")?;
|
||
seeded.downloads.seed_report(super::downloads::Report {
|
||
job: None,
|
||
// 出图要能看见「试过哪些源、各自为什么」:两条真实形态的失败。
|
||
tries: vec![
|
||
super::downloads::Try {
|
||
source: "tuna".to_string(),
|
||
kind: unlucky_core::download::DownloadErrorKind::NotFound,
|
||
},
|
||
super::downloads::Try {
|
||
source: "github".to_string(),
|
||
kind: unlucky_core::download::DownloadErrorKind::Timeout,
|
||
},
|
||
],
|
||
success: None,
|
||
failure: Some(super::downloads::Failure {
|
||
major: 21,
|
||
kind: unlucky_core::game::java::JavaErrorKind::Network,
|
||
source: Some("github".to_string()),
|
||
}),
|
||
});
|
||
return Some(seeded);
|
||
}
|
||
_ => return None,
|
||
}
|
||
Some(state)
|
||
}
|
||
|
||
/// 出图用的「当前实例要求」(`1.20.5` 起要 21)。
|
||
fn download_context(minimum: u32) -> Context {
|
||
Context {
|
||
required: Some(Requirement {
|
||
instance: "生存服".to_string(),
|
||
version: "1.20.5".to_string(),
|
||
minimum,
|
||
maximum: None,
|
||
}),
|
||
layer: Some(Layer::Global),
|
||
effective_memory_mb: Some(4096),
|
||
}
|
||
}
|
||
|
||
/// 出图用的三键:自定义落点 + 自己排的顺序(第一行不是默认的那家)+ 自动准备开着。
|
||
fn seeded_prefs() -> super::prefs::Prefs {
|
||
super::prefs::Prefs {
|
||
install_root: "D:/Java".to_string(),
|
||
saved_install_root: "D:/Java".to_string(),
|
||
auto_install: true,
|
||
saved_auto_install: true,
|
||
priority: vec!["microsoft", "temurin", "oracle", "zulu"],
|
||
saved_priority: vec!["microsoft", "temurin", "oracle", "zulu"],
|
||
}
|
||
}
|
||
|
||
/// 出图用的生效值(与 [`seeded_prefs`] 一致:落点与顺序都来自设置)。
|
||
fn seeded_effective() -> super::prefs::Effective {
|
||
super::prefs::Effective {
|
||
root: "D:/Java".to_string(),
|
||
root_mode: "custom",
|
||
root_layer: super::prefs::RootLayer::Setting,
|
||
root_unresolved: false,
|
||
order: vec![
|
||
"Microsoft OpenJDK",
|
||
"Eclipse Temurin",
|
||
"Oracle OpenJDK",
|
||
"Azul Zulu",
|
||
],
|
||
order_layer: super::prefs::OrderLayer::Setting,
|
||
domestic: true,
|
||
}
|
||
}
|