Files
Unlucky-Launcher/crates/app-iced/src/pages/settings/java/seed.rs
T
AskaEth ce463cc9b5 feat(app-iced): Java 页「下载一个 JDK」+ 三个设置键(M197)
用户原话:「我们内置了那么多镜像源 甚至用户不能手动选择指定版本下载。」
「自动下载 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}` 各自成模块。
2026-11-08 20:49:56 +08:00

182 lines
7.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 「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,
}
}