//! 阶段与进度:**把导入进度映射成下载页那块面板的入参**(不另画一套进度 UI)。 //! //! ## 任务书第 5 条怎么落 //! //! 「沿用既有安装面板组件与状态机,禁止再写第二套进度 UI」—— //! //! 1. 导入的 `ImportStageView` / 计数 / 当前路径先映射成 [`InstallProgressView`](本文件 //! [`panel_progress`]); //! 2. 画法交给 `pages::download::install_panel`(M109 已经打过薄包装,同一个函数、同一套几何 //! 与文案); //! 3. 面板只认四个粗阶段(规划 / 下载 / 安装 / 登记),任务书要的「解包 / overrides / 补文件」 //! 三档由**一行步骤说明**([`stage_line`])承载。 //! //! 第 3 点不是第二套进度 UI:多出来的只是一句文字,进度条、计数行、取消按钮仍然只有那一份。 //! 为什么不再造一条按 `ImportStageView` 五档划分的进度条:那正是「第二套」的定义,而且两块条 //! 同时出现时用户不知道该信哪一条。 use unlucky_i18n::{Catalog, Key}; use unlucky_presenter::dto::{ ImportProgressView, ImportStageView, InstallProgressView, InstallStage, }; use crate::pages::download::Download; /// 抛进面板的进度行。 #[derive(Debug, Clone, PartialEq)] pub struct Running { /// 包名(面板标题那一行) pub pack: String, /// 细档位说明(`步骤 2/5 · 解包覆盖内容`) pub stage_line: String, /// 交给下载页那块面板的进度(**唯一**的进度形状来源) pub panel: Download, } /// 细档位说明(`步骤 2/5 · 解包覆盖内容`)。 #[must_use] pub fn stage_line(stage: ImportStageView, catalog: Catalog) -> String { let total = ImportStageView::ALL.len(); let index = ImportStageView::ALL .iter() .position(|item| *item == stage) .map_or(1, |at| at + 1); catalog.render( Key::PackStageLine, &[ ("index", &index.to_string()), ("total", &total.to_string()), ("stage", catalog.text(stage_key(stage))), ], ) } /// 阶段 → 文案 key。 #[must_use] pub const fn stage_key(stage: ImportStageView) -> Key { match stage { ImportStageView::Probe => Key::PackStageProbe, ImportStageView::Extract => Key::PackStageExtract, ImportStageView::Fetch => Key::PackStageFetch, ImportStageView::Commit => Key::PackStageCommit, ImportStageView::Register => Key::PackStageRegister, } } /// 导入阶段 → 安装面板的粗阶段(**唯一映射处**)。 /// /// `Extract` / `Commit` 都落到 `Installing`:对那块面板而言它们都是「在写盘」,区别由 /// [`stage_line`] 说给用户。 #[must_use] pub const fn panel_stage(stage: ImportStageView) -> InstallStage { match stage { ImportStageView::Probe => InstallStage::Planning, ImportStageView::Extract | ImportStageView::Commit => InstallStage::Installing, ImportStageView::Fetch => InstallStage::Downloading, ImportStageView::Register => InstallStage::Registering, } } /// 导入进度 → 下载页面板的入参。 /// /// `version` / `instance` 都填包名:面板第一行显示的就是「这次在装什么」, /// 而导入的对象是包,不是某个版本 id。 #[must_use] pub fn panel_progress(progress: &ImportProgressView) -> InstallProgressView { InstallProgressView { version: progress.pack.clone(), instance: progress.pack.clone(), loader: String::new(), stage: panel_stage(progress.stage), files_done: u64::from(progress.done), files_total: u64::from(progress.total), bytes_done: 0, bytes_total: 0, speed_bps: 0, eta_secs: 0, message: progress.current.clone().unwrap_or_default(), } } /// 进度事件 → 面板要的视图模型。 pub(super) fn running_of(progress: &ImportProgressView, catalog: Catalog) -> Running { Running { pack: progress.pack.clone(), stage_line: stage_line(progress.stage, catalog), panel: Download { install: Some(crate::pages::download::install_view( &panel_progress(progress), catalog, )), ..Download::loading() }, } }