Commit Graph
4 Commits
Author SHA1 Message Date
AskaEth fa53d72f73 feat(nav): M300 导航轨折叠按钮 + 折叠宽度令牌 + 宽度过渡与落盘
用户原话「默认左侧固定,允许折叠」:M297 盘查确认 iced 从来没接过折叠按钮,
presenter 的 toggle_nav/nav_collapsed 是 Slint 遗留、唯一调用方在已退役的 crates/app。

## 令牌(先定数值再动手)
- nav_collapsed_width = 56 + 2 × Space::X1 = **64**:胶囊(M283 定稿 56×32,本轮不动)
  两侧各留 4px 才不被裁切;旧值 48 的死因写进注释(48 − 2×4 = 40 < 56)。
- 断言:折叠宽 ≥ 胶囊宽 + 2×X1、≥ touch_target 48、在 4px 栅格上。

## 折叠按钮与折叠态
- 按钮放**轨底、头像位之上**:轨顶一个像素都不动(M283/M299 的展开态对照图仍可比),
  轨底本来就是「固定贴底」的槽,两态下位置不变。几何与导航项同一套(56×32 药丸 + 52 命中高)。
- 折叠态:隐藏文字标签与账户名,每项/头像/按钮都补 M3 气泡 tooltip(折叠态不许是一列无名符号);
  纵节奏不变(项高仍 52),所以切换时图标不上下跳。五项图标两两不同由用例钉住。

## 动效(复用底盘、零新常数)
- 帧泵加**第二条并列宽度轨**(nav ⇄ rail),时长/曲线复用同一张 rail_spec();
  借用右栗那条会让左轨折叠改掉右栗的目标(暗耦合),tower 已否掉那个方案。
- 起跑在 update 侧;启动按落盘档对表(幂等,仅在没有轨道在跑时);折叠**不置 view_dirty**
  —— 宽度在 view 里逐帧采样,帧由轨道自己续,跑完 needs_frames() 回 false。

## 落盘(任务要求「重启读回仍折叠」)
- core schema 登记 ui.nav.collapsed(纯增量 bool,不碰 schemaVersion);presenter 桥加
  load/persist 一对(走唯一写入口 write_with,现读→改→落盘);启动 construct 读回。
- 截图通道不读用户配置(D30),折叠态出图走 ULL_NAV_COLLAPSED=1。

## 判据
- app-iced: 1053 passed(新增 3 条接线用例 + 7 条 shell/几何/树结构用例 + 6 条帧泵用例);
  presenter: 408 passed(新增落盘往返 1 条);fmt / clippy --workspace --all-targets 均 0。
- 变异实验:删 observe_nav ⇒ 宽度停在 88 红;删启动对表 ⇒ 首次展开硬跳红。
- 像素(DevDocs/artifacts/m300/):折叠态内容左缘 112→88(24px 真回收)、药丸两态都 56 宽
  且折叠档右缘 59 < 64(不裁切)、图标行是展开态子集(纵节奏不变)。

## 已知偏离(已登记,tower 批了紧随 mission)
crates/app-iced/src/pages/layout.rs 的 rail_width() 仍是 const fn(恒 88),所以折叠态内容块
宽度不变、整块左移 24px ⇒ 右侧多一条 24px 空白带(像素图里保留、未裁)。
2026-11-13 16:15:16 +08:00
AskaEth 0d917e88da feat(settings): M299 选中项收口到 selected_fill + 分组导航改真按钮 + tabs 用 status
- pages/settings/frame.rs:分组导航从 mouse_area 换成 button(四态可辨),
  几何不变(ShapeScale::Full 胶囊),颜色走唯一的 selected_fill;forced 从
  settings::view 递下来,于是 --force-state 能拍到这一处
- language / theme / appearance choice 三处「选中档位」补状态层
- components/selection/paint/chip.rs:选中分支用上 state 参数
- shell/nav.rs / shell/nav/account.rs:两处私有拷贝收口到 selected_fill(几何没动)
- components/navigation/tabs.rs:状态层在样式闭包里跟 button::Status 求值
- 新增门禁 selection/tests/single_entry.rs:11 个站点必须调 selected_fill +
  产品代码里不许再出现 or_else(|| Some(ui.color( 这个私有拷贝形态
- 行数:frame.rs / nav.rs / appearance::section 的单测按「纯搬移」拆出去
2026-11-13 14:41:57 +08:00
AskaEth 813ec88d89 fix(app-iced): 导航轨 hover/pressed 状态层落回药丸(M283)
`rail_item` 里同一个元素并存两种形状:选中画 56×32 `radius(Full)` 的药丸,
而 hover/pressed 走 `button(stack).style(..)`,底色铺在整个按钮上
(88×52,`Border::default()` ⇒ r=0)。用户原话就是这一处:「侧边栏按钮
hover/click 是父容器整个方形区域颜色加深,而不是 MD3E 应有的胶囊 UI」。

改法照 `components/navigation/drawer/item.rs`(全仓唯一正确的导航实现):

- 状态层改由药丸自己的 `container.style` 求值,经 `interaction::layer_color`;
  选中/未选中两条分支不合并(选中静息兜底 `SecondaryContainer`,未选中兜底 `None`);
- `base` 取 `MaterialLayer::Canvas.surface_role()`(导航轨画的就是 Canvas),不写字面量角色;
- `button.style` 的 `background` 恒为 `None` —— 按钮不再有任何形状上的主张;
- `interaction::tracked` 只在 `forced.is_none()` 时套(强制态是取证,不许有过渡中间帧);
- 轨底账户位同型:状态层落在头像那个 Ø40 圆上,不是 88×52 的按钮;
- 药丸几何收敛到 `state_layer_box()` 一个定义点(`rail_item` 与单测都读它)。

判据:
- `shell::tests::the_state_layer_is_drawn_on_the_pill_not_across_the_rail`(几何)
- `shell::tests::the_rail_never_paints_its_state_layer_on_the_button`(结构:扫源码,
  `button(stack)..on_press` 闭包里不许出现 `Background::Color`、`tracked` 必须有
  `forced.is_none()` 守卫)。两条都做过反向验证:把写法改回去,两条同时红。

取证(`DevDocs/artifacts/navpill/`):`--force-state=rest` 与改前**逐字节相同**
(md5 1ebb611b3edc156925ca802d3f4fa76d);hover/pressed 的高亮区从 88×52 矩形
变成 56×32 药丸(四角为空),账户位从 88×52 变成 Ø40 圆。
2026-11-12 21:42:30 +08:00
AskaEth 1ff00bbe50 feat(app-iced): M114 账户页三轨登录(微软正版 / 第三方皮肤站 / 本地档案)
- 账户页:当前账户卡 + 全部账户列表 + 空态三入口 + 皮肤区;五项动作(添加/切换/删除/重新登录/校验)
- 三轨添加流程:设备码(用户码+链接+倒计时+过期重试+取消)、授权码(浏览器+可复制链接+取消)、
  本地档案(名字校验)、第三方站(服务地址 + 服务发现校验 + 密码登录,密码掩码且用完即弃)
- 导航:账户为一等页,入口是轨底头像位(未登录=描边剪影 / 已登录=首字母块+名字;窄高收成图标条)
- 凭据红线:DTO 侧形状脱敏 + 状态层二次脱敏 + 密码掩码;Inject-JWT 测试断言视图模型干净(已做变异取证)
- presenter:authlib 登录/服务发现/皮肤抓取(复用下载引擎的 HTTP 客户端,无新增依赖)、
  皮肤原图经 DTO 到 UI 裁剪成头像(既有 image 依赖,未改 Cargo.toml)
- i18n:新增 account 域 51 条中英文案(离线档案口径全量写入),金表同步
2026-11-05 05:08:35 +08:00