D45 封顶轮的最后一改,只动这三条: - **P2-3 逐环断言(假绿)**:环本来就在固定 x 栅格(24 + 56·i、宽 40),判据从「主色连通簇数 非空」改成**六个窗逐个测**「窗内墨迹(轨道 ∪ 激活并集)外接成 40(±2)×40(±2)、且不越窗」, 外加「1..5 号窗必须有激活色弧」。簇数只打印不再当判据。G18-i 从「欠账」改成**已收口**, 并删掉模块文档里「要么把 6 个环摆成固定 x 栅格」那句错话(它们本来就在栅格上)。 环带定位也换过两版(「每行墨点 4..20」会把 40 切成 32;「首行..末行」在深色档扩到 274 行), 最终用「第一个窗里连续有墨、高度≈40 的行组」。 变异:涂掉 4 个环 → `第 1 个窗里没有任何环墨迹:环丢了` 红;25% 环缩成 20×20 → `第 1 个窗里的环应 40×40(±2),实测 20×20` 红。 - **P2-1 贴顶边距**:新增「框顶行 → 条顶行 = 36±1」与「取景框高 = 96±1」两条。 变异(`HOST_SHORT` 96 → 72,重编重拍):`D:贴底 ⇒ 框顶到条顶应为 36(96 − 48 − 12),实测 12` 红; 还原后绿。—— 之前只量「条底距框底」,宿高回退成 72 时确实抓不住。 顺带修了取景框判据本身:条自身(深色)比画布更接近框色,会把条自己认成框(实测差值 1), 现在要求「框色连续段比条本身更宽」。 - **P2-2 Dialog 下限**:补单测 `effective_width(200.0) == 280.0`(360/800 两点一并钉住), 并把「不低于官方 280」写进 `Dialog::width` 的文档。 - 欠账登记(只写表、不改代码):G18-j(动作色用全图合计,单卡漂移可能被别卡盖住)、 G18-k(再 4 处文档残留,不为凑数扩大 diff)、G18-l(取景框判据会把条的抗锯齿底行算成框, 余量 0.0008,方向是误报;加了「框高 96」后触发概率下降)。
93 lines
6.2 KiB
Rust
93 lines
6.2 KiB
Rust
//! **反馈类家族**:Progress(§12)/ Snackbar(§14)/ Dialog(§7)/ EmptyState(§15)。
|
||
//!
|
||
//! ## 接口(契约 §2 + §8:官方名的小写形式,对消息类型泛型,不 import `app::Message`)
|
||
//!
|
||
//! | 组件 | 入口 | 消息要求 |
|
||
//! |---|---|---|
|
||
//! | 线性进度 | [`linear(ui, Progress::determinate(0.5))`](linear) | **无消息**(进度不可点) |
|
||
//! | 环形进度 | [`circular(ui, Progress::indeterminate(phase))`](circular) | **无消息** |
|
||
//! | 提示条 | [`snackbar(ui, Snackbar::new("…").action("撤销", msg))`](snackbar) | 有动作/关闭时才要 `M` |
|
||
//! | 对话框 | [`dialog(ui, Dialog::new("标题", "正文").double(..))`](dialog) | 有动作时要 `M` |
|
||
//! | 空态 | [`empty_state(ui, EmptyState::new(icon, "标题", "说明"))`](empty_state) | 有 CTA 时要 `M` |
|
||
//!
|
||
//! 全部 `M: Clone + 'a`(与按钮家族同一口径),`Ui` 一律 `&'a Ui` 传入、组件内不 `Ui::new`。
|
||
//!
|
||
//! ## 三条硬口径(每个组件文件开头各有一套细则表)
|
||
//!
|
||
//! 1. **数值来自哪里**:颜色/字级/圆角/内距走令牌(`Role` / `TypeRole` / `ShapeScale` / `Space`),
|
||
//! 进度厚度、Snackbar 宽高、Dialog 宽、空态块这四组令牌层没有 → 登记 **G17**([`geometry`])。
|
||
//! 2. **状态层只有一处**:hover/pressed 的叠色一律经 [`interaction::overlay_color`];
|
||
//! 禁用内容默认经 [`interaction::disabled_content_over_role`],但**动作件是个例外**——
|
||
//! `action.rs` 的 `content_color()` 把 38% 内容色叠在它**自己的容器角色**上
|
||
//! (`InverseSurface` / `SurfaceContainerHigh`),因为 `interaction` 那两档只认
|
||
//! 「叠在 Surface / 12% 容器上」;
|
||
//! 禁用是**状态**(`on_press: Option<M>` 为 `None`),不是另一个构造器(M77 之前 Chip 踩过)。
|
||
//! 3. **精确尺寸经 `layout`**:图标/几何图元一律 `layout::fixed` / `layout::centered_fixed`(Q9),
|
||
//! 居中一律父级 `align_x/align_y`(Q8,不许 `center_*`)。
|
||
//!
|
||
//! ## CPU 降级(D27)与「不画阴影」
|
||
//!
|
||
//! 本家族零模糊、零运行时半透明:进度条是实色、Dialog 的 scrim 是**预合成实色**
|
||
//! ([`scrim`]),两个浮层都不画阴影(`ShadowSpec` 还是 M63 占位值 + D27 禁模糊)。
|
||
//! 四条偏离逐条登记在报告里(D-1 无阴影 / D-2 scrim 预合成 / D-3 波浪未实现 / D-4 Snackbar 无阴影),
|
||
//! 另有一条**观察项** D-5(深色档 scrim 只压暗 4%,见 `dialog.rs` 的 scrim 一节)。
|
||
//!
|
||
//! ## 逐项偏离登记(提交报告里同一份表)
|
||
//!
|
||
//! | 编号 | 参考 | 我们 | 理由 | 可修 |
|
||
//! |---|---|---|---|---|
|
||
//! | D-1 | Dialog L3 阴影 | 无阴影 | D27 CPU 禁模糊 + `ShadowSpec` 为 M63 占位 | 是(等 M63 阴影表 + 双档渲染) |
|
||
//! | D-2 | scrim 真半透明 @0.32 | 预合成实色 | D27 CPU 零半透明;遮罩下是底色时逐像素等价 | 是(GPU 档可切真 α) |
|
||
//! | D-3 | 线性波浪 3/40、环形 1.6/15 | 直线段 / 等弧长 | `12b §12.4` 明确允许,登记后用匀速替代 | 是 |
|
||
//! | D-4 | Snackbar L3 阴影 | 无阴影 | 同 D-1 | 是 |
|
||
//! | G17-d | Snackbar 最小宽 344 | 组件不强制(宿主保证) | iced `Length` 无 min-width(同按钮 G15) | 是(自定义 Widget) |
|
||
//! | D-5 | 深色档 scrim 压暗 32% | 保持 0.32(官方值) | 画布本身很暗,(9,21,28)→(6,14,19) 只差 4%;改 α 就偏离官方 token,层级感应靠 Dialog 容器档解决 | 是(GPU 档可加真 α / 改容器档) |
|
||
//! | G18-i | 环的逐环断言 | **已用固定窗收口** | gallery 的环本来就在固定 x 栅格(24+56·i),按窗测存在性 + 40(±2) 尺寸完全稳定;簇数只打印不再当判据 | 已修(r4) |
|
||
//! | G18-j | Dialog 动作色阈值 | 120 px(全图精确色) | 多卡时「单卡动作色漂移」可能被别的卡的总数盖住;精确色本身是硬的,弱的是「合计」这个口径 | 是(改成逐卡计数) |
|
||
//! | G18-k | 文档残留 | 本轮只改了能确证的行 | 复审又找出 4 处同类残留;不为凑数扩大 diff,留待下次触碰该文件时顺手改 | 是 |
|
||
//! | G18-l | snackbar 取景框判据 | 「更靠近框色而不是画布」 | 条自身的抗锯齿底行覆盖率实测 0.5008(余量 0.0008),可能被算成框 ⇒ **误报方向**(不是假绿);加了「框高 96」之后触发概率下降 | 是(改用精确色 + 容差,或自绘取景框) |
|
||
//!
|
||
//! ## 文件地图
|
||
//!
|
||
//! ```text
|
||
//! geometry.rs G17 常量 + 五组几何(含不定态 keyframes)
|
||
//! keyframes.rs 相位 → 进度 的纯函数求值器(组件不计时)
|
||
//! progress.rs linear / circular(含环形 SVG 图元)
|
||
//! snackbar.rs 提示条 + 贴顶/贴底
|
||
//! dialog.rs 对话框 + scrim
|
||
//! empty_state.rs 空态(项目自定:`[估]` 几何 + `[规格]` 排版 + 一条 `[源]` CTA)
|
||
//! action.rs 文字动作 / 图标动作(Dialog 与 Snackbar 共用)
|
||
//! gallery_parts.rs 家族自己的 gallery 段落开关(`ULL_FEEDBACK_PART`)
|
||
//! probe.rs 渲染层像素断言(对着 gallery 截图量,见其模块文档)
|
||
//! ```
|
||
//!
|
||
//! ## 桩期的 `demo()` 已删除(不是签名被改)
|
||
//!
|
||
//! M75 的占位 `demo()` 只画一行「pending」文字,没有任何验收价值;真组件的验收画面就是
|
||
//! `gallery/feedback.rs` 的四段矩阵。契约 §9.3「家族 `demo()` 签名是共享契约」约束的是
|
||
//! **别改别人的调用点**——`feedback::demo` 自始至终只有 `gallery/feedback.rs` 一个调用点,
|
||
//! 而那个文件就在本 mission 的 scope 内,所以这里连同调用点一起换成了真组件(不留死代码:
|
||
//! 一个没人调用的 `pub fn` 会直接触发 `dead_code`,`-D warnings` 门禁会红)。
|
||
|
||
mod action;
|
||
pub mod dialog;
|
||
pub mod empty_state;
|
||
pub mod gallery_parts;
|
||
pub mod geometry;
|
||
pub mod keyframes;
|
||
pub mod panel;
|
||
pub mod progress;
|
||
pub mod snackbar;
|
||
|
||
#[cfg(test)]
|
||
mod pixel;
|
||
#[cfg(test)]
|
||
mod probe;
|
||
#[cfg(test)]
|
||
mod tests;
|
||
|
||
pub use dialog::{dialog, scrimmed, Dialog};
|
||
pub use empty_state::{empty_state, EmptyState};
|
||
pub use progress::{circular, linear, Progress};
|
||
pub use snackbar::{snackbar, Placement, Snackbar};
|