feat(app-iced): M90 —— app.rs 拆成 src/app/ + presenter 真接线 + 实例页端到端
拆分(行为不变,截图四件套逐字节相同):
- 400 行的 app.rs 拆成 src/app/{mod,state,message,update,subscription,view,boot,tests}.rs,
每个文件 ≤ 300 行;components 的 #[path] 跟着搬到 src/app/mod.rs(逻辑路径仍是 crate::app::components),
可见性放到 pub(crate) 让页面层能用真组件。
- 拆分前后各出 shell/gallery 浅深四张图,cmp 全部 IDENTICAL。
presenter 接线(crate 文档 §4):
- App 持有 Box<dyn Backend> + SettingsBridge + AppState;启动 build_backend + SettingsBridge::open + AppState::new。
- 截图通道强制 mock(D30 可复现);交互模式走真 host,--data-dir 从 M90 起真的被消费。
- Boot 抽干首屏快照(第 3 帧落盘,等节拍会把空页面拍进图);节拍 = 帧事件 + 33ms 时间闸门
(iced::time::every 要 tokio/smol,见 finding),tick → drain_events → AppState::apply。
- 用户动作不乐观回显:Launch/Stop 走 Backend::dispatch,状态等事件回来才变。
- 路由:pages::Message::Navigate(Route) 直接进 AppState::navigate,选中项 = 路由栈顶(不再有本地副本);
首屏自动选中第一行(list-detail 桌面惯例),只做一次。
实例页打通(其余三页保留占位视觉 + Message/update + 路由):
- 列表行换成 components::navigation::ListItem(真五态/选中),页头与详情动作换成 components::buttons
(Play 是唯一的实心 accent),分隔线换成 components::divider。
- 数据全部来自 presenter 快照:VERSION/LOADER/ISOLATION/VERSION ID/FILES/LAST PLAYED + 运行状态行。
- 导航轨换成真 NavigationRail(88),5 项各自压/替换路由。
版面约束未破(实测):列表列 336、正文列 424(元信息卡 206+12+206,右缘 896)、rail 88(药丸 16..71)、
断点 600/840 走 frame_metrics;新增 pages/tests.rs 的 9 条数值断言钉住它们。
This commit is contained in:
1 parent
270026338f
commit
b484998fc9
17 files changed
+1990
-676
No files matched your search
@@ -176,6 +176,32 @@ pub fn text_role<'a>(
|
||||
text_widget(ui, role, emphasized, content, color).into()
|
||||
}
|
||||
|
||||
/// 同 [`text_role`],但文案是**拥有的**字符串(计数、时间戳这类运行时格式化出来的短串)。
|
||||
///
|
||||
/// 为什么需要它:文字控件**借用**它的内容(`&'a str`),所以 `format!` 出来的临时串不能直接进树;
|
||||
/// iced 的 `text()` 接受 `String`(`IntoFragment` 为 `String` 实现了 owned 分支),这里把
|
||||
/// 「令牌化 + owned 内容」两件事合成一处,页面就不必为了一个计数往视图模型里塞字段。
|
||||
pub fn text_role_owned<'a>(
|
||||
ui: &Ui,
|
||||
role: TypeRole,
|
||||
emphasized: bool,
|
||||
content: String,
|
||||
color: Color,
|
||||
) -> Element<'a, Message> {
|
||||
let style: TypeStyle = if emphasized {
|
||||
ui.emphasized(role)
|
||||
} else {
|
||||
ui.style(role)
|
||||
};
|
||||
|
||||
iced::widget::text(content)
|
||||
.size(style.size_px)
|
||||
.line_height(LineHeight::Absolute(Pixels(style.line_height_px)))
|
||||
.font(ui.font_of(style))
|
||||
.color(color)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// 同 [`text_role`],但**文字自身居中**(空态的标题与副文案:图标块是居中锚点)。
|
||||
pub fn text_role_centered<'a>(
|
||||
ui: &'a Ui,
|
||||
|
||||
Reference in new issue
Block a user