Files
Unlucky-Launcher/crates/app-iced/src/pages/settings/java/downloads/recommend.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

43 lines
1.7 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.
//! 「现在该推荐哪一档」(M197):`java.auto_install` 的唯一消费者。
//!
//! 从 `downloads.rs` 拆出来(那个文件加了作业槽与事件映射之后越过 400 行硬线)。
//! 纯函数:只读「当前实例要求 + 已扫到的运行时 + 这个键」,不联网、不落盘。
use unlucky_core::game::java::catalog;
use crate::pages::settings::java::context::Requirement;
use crate::pages::settings::java::row::RuntimeRow;
/// 「现在该推荐哪一档」:`java.auto_install` 的真实消费者。
///
/// 语义(就是界面上那句 hint):**开着**时,只有当「扫到的 JDK 里没有一个满足当前实例的要求」
/// (没有实例时 = 一个 JDK 都没有)才推荐一档;推荐的是当前实例最低要求对齐到目录的那一档
/// ([`catalog::default_major`],没有实例时 = 基准 17)。**关掉**就一律不推荐,用户自己挑。
///
/// 为什么不直接自动开始下载:那是 180 MiB 起步、且用户可能只想手动指定 JAVA_HOME。
/// 「替你选好一档 + 一句话说明」把决定权留在用户手上,同时把「该装哪个」这件知识给出去。
#[must_use]
pub fn recommend(
required: Option<&Requirement>,
runtimes: &[RuntimeRow],
auto_install: bool,
) -> Option<u32> {
if !auto_install {
return None;
}
let satisfied = match required {
Some(required) => runtimes.iter().any(|runtime| {
runtime
.major
.is_some_and(|major| required.satisfied_by(major))
}),
None => !runtimes.is_empty(),
};
if satisfied {
return None;
}
Some(catalog::default_major(
required.map(|required| required.minimum),
))
}