fix(app-iced): M109 r1 —— CF 来源装入闸门、has_more 读最近一页、末行切半与文案/图标
复审 p1-2items 的两条 P1 与三条 P2,逐条收口。 `blockers_of` 只看版本/加载器/目标实例,不看来源;而 host 的 `resolve_file` 对 CF 直接 返回「未接通」⇒ 切到 CF 源后每条都必然失败,UI 一声不响。 - 新增 `Blocker::SourceNotWired` + 文案 `ContentSourceNotWired`(中英); - `blockers_of` 的入参从 `Option<(&[String], &[String])>` 收成 `Option<HitFacts>`(版本 / 加载器 / **来源**),两处调用点(产品路径、演示数据)一起改; - 判据同构于整合包的 `NeedsPipeline`:**点之前**禁用并给一条原因;CF 文件端点接通后删掉这条。 DTO 的 `has_more()` 判「本页装满」是对的,但 reducer 在 `offset>0` 时先 extend 再判, 被判定的是**累计条数** ⇒ 首页满 20 条之后恒真:「加载更多」永不消失、「没有更多了」在 真实翻页路径上不可达,且每点一次白发一次网络请求。 - `ContentState` 新增 `last_page_filled`(**先**按这一页记一位,再并进累计列表); - 页面的 `has_more` 读它(`&& !pending`);换条件(offset 归零)时清位; - 新增 `crates/presenter/src/state/content_tests.rs` 四条用例(state.rs 贴 400 行上限,拆文件): `a_short_last_page_clears_has_more` / `an_empty_last_page_keeps_has_more_false` / `changing_the_query_resets_the_page_flag` / `a_stale_batch_does_not_touch_the_page_flag`; - 变异自证:把判据改回「读累计」后前两条红(`末页不满 ⇒ 不许说还有更多`、`空页 ⇒ 没有更多`), 改回绿。 - **末行被 footer 切半**(复审定位的真因):`view.rs` 的 body 列漏了 `.spacing(..)`,而列表 纵向内边距是 0 ⇒ 视口底边正好切在半行上。补 `Space::X2`,并说明为什么必须给。 - **文案去掉开发者术语与内部编号**:`ContentSourceUnavailable` 不再写 `ULL_CF_API_KEY` (改「CurseForge 需要在设置里配置密钥才能搜索」);`ContentModpackNotReady` 不再写 mission 编号(改「整合包安装尚未开放」);host 侧那条 `InstallProgress` 失败文案同步去编号。 - **图标**:四类改为 `Folder` / `Plus` / `Restore` / `Expand`——不借用导航五枚(同屏撞形, 复审 P2-3)、不用填充字形(`no_hardcoded_tokens` 门禁);偏离表按**实际取值**重写,并补一条 「CF 的装入也是禁用态」的登记。 - 演示数据加 `ULL_CONTENT_STATE=cf` 一屏,出图证明 P1-1 的禁用态(`12-cf-not-wired-light.png`)。 门禁(逐条落盘退出码,不走管道):fmt 0 / clippy `-D warnings`(app-iced+presenter+i18n)0 / `cargo test -p unlucky-app-iced --lib` 0(451 passed)/ `cargo test -p unlucky-presenter` 0 (174 passed)/ `cargo test --workspace --exclude unlucky-app` 0。改动文件最大 397 行。 取证:`DevDocs/artifacts/m109/`(12 张,全部重出)
This commit is contained in:
1 parent
6b161227d8
commit
42099d4336
13 files changed
+246
-40
No files matched your search
@@ -18,7 +18,7 @@
|
||||
use unlucky_i18n::{Catalog, Lang};
|
||||
use unlucky_presenter::dto::{ContentHit, ContentKind, ContentSort, ContentSource, LoaderKind};
|
||||
|
||||
use super::model::{blockers_of, Content, ContentQueryView, Hit, Status, Target};
|
||||
use super::model::{blockers_of, Content, ContentQueryView, Hit, HitFacts, Status, Target};
|
||||
use crate::pages::download::Download;
|
||||
|
||||
/// 一个固定的演示环境:两个实例(一个 Fabric / 一个 Forge)。
|
||||
@@ -155,11 +155,19 @@ pub(super) fn demo(fallback_kind: ContentKind, lang: Lang) -> Content {
|
||||
hits(kind, catalog, state != "incompatible")
|
||||
};
|
||||
// 「不兼容」那一屏:选中的那条是 1.21.1 + Forge 的项目,而目标是 1.20.1 + Fabric
|
||||
let selected_index = if state == "incompatible" { 2 } else { 0 };
|
||||
// 「CF 未接通」那一屏:选中的那条来自 CurseForge(文件端点还没接,按钮必须禁用)
|
||||
let selected_index = match state.as_str() {
|
||||
"incompatible" => 2,
|
||||
"cf" => 1,
|
||||
_ => 0,
|
||||
};
|
||||
let selected = list.get(selected_index).map(|hit| hit.id.clone());
|
||||
let blockers = blockers_of(
|
||||
list.get(selected_index)
|
||||
.map(|hit| (hit.versions.as_slice(), hit.loaders.as_slice())),
|
||||
list.get(selected_index).map(|hit| HitFacts {
|
||||
versions: hit.versions.as_slice(),
|
||||
loaders: hit.loaders.as_slice(),
|
||||
source: hit.source,
|
||||
}),
|
||||
kind,
|
||||
&targets,
|
||||
target.as_deref(),
|
||||
|
||||
Reference in new issue
Block a user