feat(m162): Modrinth 在线内容源(匿名)+ 远端条目按 sha512 补全 + 离线态
core:新增 addon::online —— 按 Modrinth v2 真实形状建模(search facets / project /
project versions / version_file by hash),网络出口只有 Transport 一个 trait,生产实现
EngineTransport 走既有 DownloadEngine::download_bytes(零新依赖);错误分大类,网络类
失败映射成 NotConnected(= 未联网),不再用空列表冒充「没有结果」。
core:online::download::download_verified —— sha1 交给引擎流式校验、sha512 落盘后复核
(download::HashAlgo 没有 Sha512,改它超出 scope,已登记 finding),不符/失败删文件重试,
最多 3 次尝试且不留半截文件。
core:远端条目补全 —— PackFetcher::modrinth_file_by_sha512(默认 Unsupported = 补不出),
import 管线与新增的 scan_pack_online 都会在「有 path 但缺 hashes.sha1」时按 sha512 反查;
补出的 sha1 走 M160 同一套 judge 与合并判定,补不出仍进 unknown_remote 计数(口径未改)。
DownloadEngineFetcher 改用 download_verified,FetchRequest 增 sha512。
presenter:Modrinth 检索/详情改由 core 的 online 客户端提供(不再自己拼 URL、不再读错
date_modified);ContentFailure{kind} 取代裸字符串,无网 = Offline;新增
ContentDetailRequest/ContentDetail + LoadContentDetail 命令与 CoreEvent::ContentDetail 通道;
预检改走 scan_pack_online;内容库安装也走 download_verified(sha1+sha512)。
app-iced:Status::Offline 独立一态(未联网 ≠ 空列表 ≠ 普通失败),详情面板消费新 DTO
显示可用版本;选中项目即拉详情。i18n 新增 6 个键并同步金表。
测试:online 模块 24 个离线用例(录制 JSON + 假字节:搜索/详情/版本/按摘要反查/校验失败
即删/重试/离线分类/补全),import 侧 6 个(离线计数不变、补全后判冲突、补错摘要 ⇒ Failed),
presenter/app-iced 各补失败分类与详情状态机用例。
This commit is contained in:
1 parent
0241f793b2
commit
81278f55af
50 files changed
+3794
-222
No files matched your search
@@ -11,14 +11,16 @@
|
||||
//! | 变量 | 取值 | 作用 |
|
||||
//! |---|---|---|
|
||||
//! | `ULL_CONTENT_KIND` | `modpack` / `mod` / `resourcepack` / `shader` | 选内容类型(默认 `mod`) |
|
||||
//! | `ULL_CONTENT_STATE` | `ok` / `empty` / `incompatible` | 选状态(默认 `ok`) |
|
||||
//! | `ULL_CONTENT_STATE` | `ok` / `empty` / `incompatible` / `install` / `cf` / `offline` | 选状态(默认 `ok`;`offline` = M162 的未联网态) |
|
||||
//!
|
||||
//! 只影响本来就用演示数据的 harness 路径;产品二进制里 `demo()` 根本不会被调用。
|
||||
|
||||
use unlucky_i18n::{Catalog, Lang};
|
||||
use unlucky_i18n::{Catalog, Key, Lang};
|
||||
use unlucky_presenter::dto::{ContentHit, ContentKind, ContentSort, ContentSource, LoaderKind};
|
||||
|
||||
use super::model::{blockers_of, Content, ContentQueryView, Hit, HitFacts, Status, Target};
|
||||
use super::model::{
|
||||
blockers_of, Content, ContentQueryView, Hit, HitFacts, Status, Target, VersionRow,
|
||||
};
|
||||
use crate::pages::download::Download;
|
||||
|
||||
/// 一个固定的演示环境:两个实例(一个 Fabric / 一个 Forge)。
|
||||
@@ -147,9 +149,45 @@ pub(super) fn demo(fallback_kind: ContentKind, lang: Lang) -> Content {
|
||||
let targets = targets();
|
||||
let target = Some("survival".to_string());
|
||||
let empty = state == "empty";
|
||||
// M162:「未联网」那一屏(与空态分开画)
|
||||
let offline = state == "offline";
|
||||
// M162:详情通道的版本列表(真实路径来自 presenter 的 `ContentDetail`)
|
||||
let demo_versions = if empty || offline {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec![
|
||||
VersionRow {
|
||||
number: "mc1.20.1-0.5.11".to_string(),
|
||||
kind: "release".to_string(),
|
||||
file_name: Some("sodium-fabric-0.5.11.jar".to_string()),
|
||||
line: catalog.render(
|
||||
Key::ContentDetailVersionLine,
|
||||
&[
|
||||
("number", "mc1.20.1-0.5.11"),
|
||||
("kind", "Release"),
|
||||
("date", "2025-06-01"),
|
||||
],
|
||||
),
|
||||
},
|
||||
VersionRow {
|
||||
number: "mc1.20.1-0.5.10".to_string(),
|
||||
kind: "beta".to_string(),
|
||||
file_name: Some("sodium-fabric-0.5.10.jar".to_string()),
|
||||
line: catalog.render(
|
||||
Key::ContentDetailVersionLine,
|
||||
&[
|
||||
("number", "mc1.20.1-0.5.10"),
|
||||
("kind", "Beta"),
|
||||
("date", "2025-05-20"),
|
||||
],
|
||||
),
|
||||
},
|
||||
]
|
||||
};
|
||||
// 「装入中」那一屏:面板就是下载页那块(同一个函数),用来证明它在内容库语义下也可读
|
||||
let installing = state == "install";
|
||||
let list = if empty {
|
||||
// 空态与未联网态都**没有命中项**:离线时画出列表就是自相矛盾(列表本身就来自网络)
|
||||
let list = if empty || offline {
|
||||
Vec::new()
|
||||
} else {
|
||||
hits(kind, catalog, state != "incompatible")
|
||||
@@ -196,7 +234,13 @@ pub(super) fn demo(fallback_kind: ContentKind, lang: Lang) -> Content {
|
||||
},
|
||||
hits: list,
|
||||
selected,
|
||||
status: if empty { Status::Empty } else { Status::Ready },
|
||||
status: if offline {
|
||||
Status::Offline("connect timed out after 10s".to_string())
|
||||
} else if empty {
|
||||
Status::Empty
|
||||
} else {
|
||||
Status::Ready
|
||||
},
|
||||
total: if empty { 0 } else { 1_284 },
|
||||
// 演示数据故意把 `has_more` 置真(真实判据是「本页装满」):出图要能看到「加载更多」
|
||||
has_more: !empty,
|
||||
@@ -211,6 +255,8 @@ pub(super) fn demo(fallback_kind: ContentKind, lang: Lang) -> Content {
|
||||
None
|
||||
},
|
||||
versions: vec!["1.20.1".to_string(), "1.21.1".to_string()],
|
||||
available_versions: demo_versions,
|
||||
versions_note: None,
|
||||
draft: if empty {
|
||||
"quarkonium".to_string()
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user