//! 导航轨的**部件版**实现:`NAV` 表 + [`rail`](宽 = 令牌 `nav_rail_width` = 88)。 //! //! ## 两套 rail 的关系(M90 r3 订正,复审 P2-1;M99 把这张表从 `pages/mod.rs` 搬到这里) //! //! 产品路径(`app/view.rs`)走 `shell::view_with_content`,导航轨由 **`shell/nav.rs` 的手搓实现**画 //! ——它与 M78 组件几何同值(宽 88、药丸 56×32),复审逐像素量过「r1 产品图(真组件 rail)vs r2 //! 产品图(shell rail)在 y≥48 区域差异为 0」。组件版的 [`rail`] 只服务 `pages::app` //! (`pages_demo` 出口图、harness)与单测。 //! //! 两边的守门是分开的:`shell/nav.rs` 自带 indicator 56×32 的单测,`pages/tests.rs` 守的是下面 //! 这张表(表长 5 / 每一项都指向能高亮它的路由 / 第 5 项没有 section)。**将来哪边先漂没人拦** //! ——统一要泛型化 shell 的消息类型,成本大于收益;在那之前任何改 rail 几何的改动都要两处一起改 //! 并各自跑守门(`pages/mod.rs` 偏离登记 #10)。 use iced::Element; use unlucky_design::icons::IconKind; use unlucky_presenter::router::{NavSection, Route}; use crate::app::components::navigation::drawer::{self, Navigation}; use crate::app::components::navigation::navigation; use crate::theme::Ui; use super::Message; /// 导航轨的固定项:图标 + 标签 + 目标路由(顺序 = 自上而下)。 /// /// 顺序与 `presenter::router::NavSection` 的声明顺序一致,改这里等于改导航栏。 /// /// 可见性是 `pub(crate)`:`pages/tests.rs` 的三条断言读它(M99 从 `pages/mod.rs` 搬出来时, /// 它从「模块私有」变成「crate 内可见」,断言一条没动、强度也没降)。 pub(crate) const NAV: [(Option, IconKind, &str, Route); 5] = [ ( Some(NavSection::Instances), IconKind::Instances, "Instances", Route::Instances, ), ( Some(NavSection::Download), IconKind::Download, "Download", Route::Download, ), (Some(NavSection::Logs), IconKind::Logs, "Logs", Route::Logs), ( Some(NavSection::Settings), IconKind::Settings, "Settings", Route::Settings, ), // AI 独立页没有导航高亮项(`Route::nav()` 对它返回 `None`) (None, IconKind::Ai, "Assistant", Route::Agent), ]; /// 导航轨:**真组件**(`components::navigation` 的 rail 形态,宽 = 令牌 `nav_rail_width` = 88)。 /// /// M84 这里是一条留白带;M90 换成 M78 的 `NavigationRail`,于是「导航项 → 路由」是真的可点。 pub(super) fn rail<'a>(ui: &'a Ui, active: Option) -> Element<'a, Message> { let mut group = drawer::NavGroup::new(); for (section, icon, label, route) in NAV { let mut item = drawer::NavItem::new(label, icon, Message::Navigate(route)); if section.is_some() && active == section { item = item.selected(); } group = group.item(item); } navigation(ui, Navigation::rail().group(group)) }