feat(download): M94 下载页换成真组件 + 真快照 + 真指令(PAGEDL)
页面(crates/app-iced/src/pages/download*):
- Tabs(分类)/ ListItem(版本行)/ filled 安装按钮 / progress / EmptyState / divider
全部取自 components/ 的真组件;页头动作换成 buttons::text
- 数据只吃 pages::download::Download(app/view.rs 由 AppState 快照转,installed_only 与
download_query 照用);页面自己不留业务状态,交互只发意图
- 状态:加载(不确定进度 + 文案)/ 空(EmptyState + 刷新 CTA)/ 有数据 / 安装中 / 安装失败
(失败给可读文案 + 「打开日志」出口)
接线(追加式):
- pages::Message 加 SelectVersion / InstallVersion / CancelInstall / SetCategory
- app/update.rs 翻成 AppCommand::{InstallVersion, CancelInstall, ListVersions}
(SelectVersion 只改视图模型;「刷新」= 当前分类重新拉,全部走 RefreshAll)
- pages::Model 加 download 字段
文案:28 个 Download* key 进中英两套 catalog(一行一个 key 的全语言);页面零中文字面量,
core 的中文阶段串(InstallStage::label / message)一律不进界面
i18n 结构:catalog.rs 的既有测试模块原样外置到 catalog/tests.rs(392 行 → 282 行,
逐字未改),新 key 才装得下 400 行硬上限
测试:app-iced 276 + i18n 23 全绿;clippy -D warnings 与 fmt --check 干净
This commit is contained in:
1 parent
b3f99652bb
commit
57e8380b24
14 files changed
+1633
-247
No files matched your search
@@ -0,0 +1,72 @@
|
||||
//! 加载态与空态(**没有可用版本数据时页面不能是白屏**)。
|
||||
//!
|
||||
//! | 状态 | 触发条件(都能从快照推出来) | 画什么 |
|
||||
//! |---|---|---|
|
||||
//! | 加载 | `model.is_loading()`:快照里还没有版本列表 | 不确定态进度条 + 「正在加载版本列表…」+ 一句说明 |
|
||||
//! | 空 | `model.is_empty()`:列表拉到了,但过滤后一行不剩 | 真 [`empty_state`](图标块 96 + 24 标题 + 说明 + 一个刷新 CTA) |
|
||||
//!
|
||||
//! 两者都**不留白**:加载态给得出「还在等」的视觉证据(进度条不是装饰,是唯一的非文字信号),
|
||||
//! 空态给得出「下一步做什么」(刷新)。
|
||||
//!
|
||||
//! 拉取**失败**在这条通道上没有结构化事件(presenter 只有 `VersionListChanged`),所以列表拉不到
|
||||
//! 会停在加载态而不是谎报「没有版本」——加载态的说明文案里就写着这件事。安装失败的错误态在
|
||||
//! [`super::install`] 里(那里的 `Failed` 阶段是结构化字段,可以放心翻译)。
|
||||
|
||||
use iced::widget::column;
|
||||
use iced::{Element, Length};
|
||||
|
||||
use unlucky_design::color::Role;
|
||||
use unlucky_design::icons::IconKind;
|
||||
use unlucky_design::spacing::Space;
|
||||
use unlucky_design::typography::TypeRole;
|
||||
|
||||
use unlucky_i18n::{Catalog, Key};
|
||||
|
||||
use crate::app::components::feedback::{empty_state, linear, EmptyState, Progress};
|
||||
use crate::theme::Ui;
|
||||
|
||||
use super::super::frame;
|
||||
use super::super::{Action, Message};
|
||||
|
||||
/// 不确定态进度条的相位(没有帧订阅,取一帧静态相位;见 `install.rs` 同名常量)。
|
||||
const INDETERMINATE_PHASE: f32 = 0.35;
|
||||
|
||||
/// 加载态。
|
||||
pub(super) fn loading<'a>(ui: &'a Ui, catalog: Catalog) -> Element<'a, Message> {
|
||||
column![
|
||||
frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodyLarge,
|
||||
true,
|
||||
catalog.text(Key::DownloadLoading),
|
||||
ui.color(Role::OnSurface),
|
||||
),
|
||||
linear(ui, Progress::indeterminate(INDETERMINATE_PHASE)),
|
||||
frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodySmall,
|
||||
false,
|
||||
catalog.text(Key::DownloadLoadingHint),
|
||||
ui.color(Role::OnSurfaceVariant),
|
||||
),
|
||||
]
|
||||
.spacing(ui.space(Space::X3))
|
||||
.width(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// 空态(真 `EmptyState`:CTA 就是标准 Filled 按钮,走按钮家族)。
|
||||
pub(super) fn empty<'a>(ui: &'a Ui, catalog: Catalog) -> Element<'a, Message> {
|
||||
empty_state(
|
||||
ui,
|
||||
EmptyState::new(
|
||||
IconKind::Download,
|
||||
catalog.text(Key::DownloadEmptyTitle),
|
||||
catalog.text(Key::DownloadEmptyBody),
|
||||
)
|
||||
.action(
|
||||
catalog.text(Key::DownloadRefresh),
|
||||
Message::Action(Action::RefreshSources),
|
||||
),
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user