feat(content): 安装失败的两档分组与「只重试这些」(M191)
M186 把「可只重试失败项」算到了 core/presenter(DependencyPlan::retry_request()), 但 DTO 没字段、界面没按钮,用户拿不到。这一轮补最后一公里: - DTO:ContentFailureKind 加 Incompatible 一档(不再借 Unsupported,与「缺密钥」分开); InstallProgressView 加 retry: Vec<InstallFailureView>(project + 档位 + core 原话), 档位是专门的 InstallFailureKind(Incompatible / Unreachable,穷尽映射 core 的 FailureKind); ContentInstallRequest 加 retry: bool(重试路径唯一读的字段是 instance)。 - presenter:plan.rs 把上一轮失败的计划按 host+实例记住(与 addon/pack.rs 同一手法, host/mod.rs 不在 scope);retry_request()/retry_plan() 就是「只重试这些」—— 调 core 的 retry_request()、只请求失败的那几个项目,present 重新扫目录。 install.rs 的重试入口没有记录时回一条失败,不退化成整单重装;成功则 forget + 清名单。 - 界面:内容库页插入按档分组的失败面板(两段文案、各自条目)+「只重试这 N 个」实心按钮; 判据只有一条且在模型里(stage==Failed && 名单非空),全成功时连同按钮一起不渲染。 - i18n:新增 6 条中英文案(不兼容 / 取不到 / 只重试这 N 个 / 标题 / 提示 / 关闭),金表同步。 守门(每条都做过变异验证,见报告): ① 把 retry_request() 换成根项目请求 ⇒ retrying_asks_for_the_failed_projects_only 红(roots 变 ["sodium"]); ② 两档合并 ⇒ the_retry_list_keeps_the_two_tiers_apart / the_two_tiers_are_two_groups_with_two_labels 红; ③ 恒渲染 ⇒ a_fully_successful_install_has_no_retry_surface_at_all 红。 数据包(datapack)本轮仍未做:ContentKind 没有这一项,界面上也没有半成品入口。
This commit is contained in:
1 parent
5505ea0f91
commit
5a52f38f35
24 files changed
+1072
-24
No files matched your search
@@ -11,7 +11,7 @@
|
||||
//! | 变量 | 取值 | 作用 |
|
||||
//! |---|---|---|
|
||||
//! | `ULL_CONTENT_KIND` | `modpack` / `mod` / `resourcepack` / `shader` | 选内容类型(默认 `mod`) |
|
||||
//! | `ULL_CONTENT_STATE` | `ok` / `empty` / `incompatible` / `install` / `cf` / `offline` | 选状态(默认 `ok`;`offline` = M162 的未联网态) |
|
||||
//! | `ULL_CONTENT_STATE` | `ok` / `empty` / `incompatible` / `install` / `cf` / `offline` / `retryfail` / `retryok` | 选状态(默认 `ok`;`offline` = M162 的未联网态;`retryfail` = M191 的「有失败项」,`retryok` = M191 的「全部成功」) |
|
||||
//!
|
||||
//! 只影响本来就用演示数据的 harness 路径;产品二进制里 `demo()` 根本不会被调用。
|
||||
|
||||
@@ -19,10 +19,47 @@ 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, VersionRow,
|
||||
blockers_of, Content, ContentQueryView, Hit, HitFacts, RetryPanel, Status, Target, VersionRow,
|
||||
};
|
||||
use crate::pages::download::Download;
|
||||
|
||||
/// M191「有失败项」那一屏:两档各几个项目,面板按档分组。
|
||||
///
|
||||
/// **走真判据**([`RetryPanel::of`]),不手搓面板字段:出图与产品路径读同一个函数,
|
||||
/// 判据一改这条演示就跟着变(否则演示图能一直画着一个已经不存在的面板)。
|
||||
fn retry_failure(instance: &str, catalog: Catalog) -> Option<RetryPanel> {
|
||||
use unlucky_presenter::dto::{
|
||||
InstallFailureKind, InstallFailureView, InstallProgressView, InstallStage,
|
||||
};
|
||||
let mut progress = InstallProgressView {
|
||||
version: "Sodium".to_string(),
|
||||
instance: instance.to_string(),
|
||||
loader: "Fabric".to_string(),
|
||||
stage: InstallStage::Failed,
|
||||
files_done: 1,
|
||||
files_total: 4,
|
||||
..InstallProgressView::new()
|
||||
};
|
||||
progress.retry = vec![
|
||||
InstallFailureView::new(
|
||||
"P7dR8mSH",
|
||||
InstallFailureKind::Incompatible,
|
||||
"没有匹配所选游戏版本/加载器(1.20.1 / fabric)的版本",
|
||||
),
|
||||
InstallFailureView::new(
|
||||
"1eAoo2KR",
|
||||
InstallFailureKind::Unreachable,
|
||||
"取版本失败(online_not_found):HTTP 404",
|
||||
),
|
||||
InstallFailureView::new(
|
||||
"AANobbMI",
|
||||
InstallFailureKind::Unreachable,
|
||||
"下载 fabric-api.jar 失败(online_not_connected):连不上 cdn.modrinth.com",
|
||||
),
|
||||
];
|
||||
RetryPanel::of(&progress, catalog)
|
||||
}
|
||||
|
||||
/// 一个固定的演示环境:两个实例(一个 Fabric / 一个 Forge)。
|
||||
fn targets() -> Vec<Target> {
|
||||
vec![
|
||||
@@ -254,6 +291,12 @@ pub(super) fn demo(fallback_kind: ContentKind, lang: Lang) -> Content {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
// M191:`retryfail` 画「有失败项」,`retryok` 画「全部成功」——后者走同一条判据,
|
||||
// 得到 `None`(连按钮都不渲染)。
|
||||
retry: match state.as_str() {
|
||||
"retryfail" => retry_failure("survival", catalog),
|
||||
_ => None,
|
||||
},
|
||||
versions: vec!["1.20.1".to_string(), "1.21.1".to_string()],
|
||||
available_versions: demo_versions,
|
||||
versions_note: None,
|
||||
@@ -265,3 +308,20 @@ pub(super) fn demo(fallback_kind: ContentKind, lang: Lang) -> Content {
|
||||
pack,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// 「有失败项」那一屏的两档走**真判据**(`RetryPanel::of`),不是手搓的面板字段。
|
||||
#[test]
|
||||
fn the_failure_screen_shows_both_tiers() {
|
||||
let panel = retry_failure("survival", Lang::En.catalog()).expect("演示必须有面板");
|
||||
assert_eq!(panel.total, 3);
|
||||
assert!(panel.has_both_tiers(), "{:?}", panel.groups);
|
||||
assert_eq!(
|
||||
panel.items_of(unlucky_presenter::dto::InstallFailureKind::Unreachable),
|
||||
Some(["1eAoo2KR".to_string(), "AANobbMI".to_string()].as_slice())
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user