跨端: 导航条材质选 (a) 固定档(推翻我的 (b))—— 并修掉"注释说 (a)、代码是 (b)"的自相矛盾

pi 2026-09-15 裁定:**推翻 (b),选 (a)**。我原先给 (b) 的理由不成立,他逐条驳了:

1. **WebUI 的导航条根本不读 `--bg-blur`**:`index.css:1114` 的 `.narrow-nav` 是硬编码
   `backdrop-filter: blur(18px) saturate(1.5)`。我引这条支持"两个量不同",
   而同一条也说明**它不由用户偏好驱动**。
2. **WebUI 那个滑杆的语义是"背景"**:`BackgroundPicker.tsx:183` —— `label="模糊"`、
   `hint="虚化细节,避免背景与正文抢注意力"`、`min=0 max=24`,只作用在
   `.app-backdrop{filter:blur(var(--bg-blur))}` 上。
3. WebUI 自己留了**分开的**令牌 `--bg-blur-panel`(`index.css:267`,注释写明
   "与壁纸自身的 `--bg-blur` 分开")—— 它的词汇表本身就拒绝把两者等同。
4. **★ 我给 (b) 的理由不成立**:我写"(a) 会让那个滑杆在导航条上变成死控件",
   可那个滑杆**已经**被壁纸消费了(`MainPage.ets` 壁纸层的 `.blur(bgPlan.blurPx)`)——
   它从来**不是**导航条的控件。(a) 之下它照样是活的。
5. §7.12 的「材质(玻璃)」行原本写的就是固定档 ⇒ (a) 是**回到**已登记契约。

产品向还有一条:**导航条是 chrome,材质应当稳定**,不该因为用户换张壁纸而变厚变薄。

## 最该记的是:我的注释和代码**互相矛盾**

`MainPage.ets` 里那段注释论证的是 (a)、并明确写着"跟随是错的,pi 抓出来了",
而它下面那一行代码是 (b)。**下一个读者会照注释把代码改回去,并引我那句话当权威。**
这是这一路反复在消的形状(说的与做的不一致、而判据看不见),这次落在**注释**上 ——
而注释正是"理由要写清"那条纪律的证据源。已整段重写为真实的 (a) 版本,并把
"(a) 会让滑杆变死控件"这个**错的理由**连同它为什么错一起留在注释里。

## 做掉的东西

- `MainPage.ets`:导航条回到 `.backgroundBlurStyle(Theme.navMaterial)`;
  删掉 `NAV_MATERIAL_OF` 表与 `navMaterialFor` 的 import((a) 之下都是孤儿)。
- `model/Appearance.ts`:删 `navMaterialFor`(它存在的唯一理由就是方案 (b))。
  `blurStyleFor` 现在**没有任何调用点** —— 如实登记在它的文档注释里
  ("有测试"不等于"有人用",上一轮我刚因同形状被抓过),不假装它活着。
- **五处"整条字面表达式"断言改成语义断言**(pi §四):`cross-client-theme`、`harmony-appearance`、
  `harmony-nav`(3 处)此前都在钉
  `/\.backgroundBlurStyle\(NAV_MATERIAL_OF\[navMaterialFor\(…\)\] \?\? Theme\.navMaterial\)/`
  —— 字面换字面,正是 `CRITERIA.md` 不许的"对源码形状的匹配"。
  现在判:① 那一处的材质**来自 `Theme.navMaterial` 这个系统令牌**;
  ② **不许跟随** `bg_blur`(NavBar 真代码里不许出现 `blurPx`/`blurStyleFor`);
  ③ 令牌是 `BlurStyle` 枚举值、不是 `NONE`、且**成员名真实存在于 SDK 枚举**。
- "可达性"那条判据**随契约作废**(它守的是方案 (b)):换成判 (a) 的契约。
  **判据随契约走,不随实现走。**
- `harmony-appearance`:原先判"页面里那张表的键必须是 SDK 成员"。表删了,
  改成**枚举 `blurStyleFor` 的整个值域**(0..40 + 界外 + NaN),逐个核 SDK 成员 ——
  比原来只核表里那三行**更严**。

## 判据自己先错了一次,记下来

新判据第一版**没剥注释**就断言"NavBar 里不许出现 `blurPx`",当场红了 ——
而红的原因不是代码错,是 `NavBar` 的**文档注释**里正好写着
"我一度把档位接过用户偏好(`navMaterialFor(this.bgPlan.blurPx)`)"这句历史说明。
**注释说明禁令 ≠ 违反禁令**;不剥注释,这条判据就会变成"逼人删掉解释",
恰好与本仓库"理由要写清"的纪律相反。改成 `stripComments(bar)` 后再判,并加了一条
"注释里确实留着那处说明"的自检前提。

## 变异体:45 个全部被抓(含 3 个新判据的专属变异)

方案 (b) 落地时配的 13 个变异体**整体作废**(它们锚的代码被删了),标注 `retired`
并写清理由 —— 不是"没跑成"。另有 5 个锚点漂移(我在注释里逐字引用了被锚的那句代码,
污染了通用正则)的**重锚**到真代码;注释里那句逐字引用也一并去掉了
(**注释里逐字抄代码**正是让"按字面锚定"的变异体反复失效的根因)。
新增 3 个针对 (a) 契约的变异体(绕过令牌 / 又跟随 `bg_blur` / 令牌变 `NONE`),全部被抓。

## 未验

- **真机观感仍未验**:三档材质在真机上能不能看出差别、滑杆手感、管理页布局,
  只有真机能答。本机模拟器已起(`hdc list targets` 有目标),但
  `run-all.mjs` 的**设备闸已经到期**(8 个静态判据的前提成立)⇒ 套件现在会挡在
  那道闸上、不打 `RESULT`。**这不是本笔引入的**(前提是环境变了),已单独报给 pi。
- Go 侧 `debt_registry_test.go` 仍未在本机跑(无 Go 模块缓存);pi 已在别处跑过,绿。
This commit is contained in:
2026-09-15 11:58:19 +08:00
parent e917b8782a
commit c12744e8c3
12 changed files with 257 additions and 195 deletions

View File

@ -14,7 +14,7 @@ import { SseService, SseEvent } from '../api/SseService';
import { AppearanceStore } from '../common/AppearanceStore';
import { Configuration, ConfigurationConstant, EnvironmentCallback } from '@kit.AbilityKit';
import { image } from '@kit.ImageKit';
import { AppearanceSnapshot, isDarkMode, scrimOpacity, navMaterialFor } from '../model/Appearance';
import { AppearanceSnapshot, isDarkMode, scrimOpacity } from '../model/Appearance';
import { BackgroundPlan, PresetLayer, TRANSPARENT, resolveBackground } from '../model/Wallpaper';
import { MailSummary, Contact, PermissionRequest, DecideResponse, SentResponse, PendingResponse } from '../model/Models';
import {
@ -49,23 +49,21 @@ import {
emptyHint
} from '../model/CommTabs';
import { MailDetailParams, ComposeParams } from '../model/RouteParams';
/**
* `navMaterialFor` 给的**档位名** → SDK 的 `BlurStyle` 枚举(导航空专用)。
/*
* ⚠️ **`import` 必须在这一行的位置**:ArkTS 要求所有 import 都在**任何其它语句之前**
* (`arkts-no-misplaced-imports`),与它们之间隔的是常量、表还是别的语句无关。
*
* 与 `blurStyleFor` 的关系:同一个分档表,但 `navMaterialFor` **有下限**(永不 NONE),
* 因为"导航条是玻璃"是不变量,而壁纸可以不模糊(见 `model/Appearance.ts` 的说明)。
* 这一笔我犯过:`7647c24` 里我把一张常量表(`NAV_MATERIAL_OF`)插在了这两组 import
* **之前**,于是 `hvigorw assembleHap` 直接报错(`f31bc02`/`7647c24` 上都红)。
* **归属说明**:那条错是我造成的,`git show 7647c24:…/MainPage.ets` 可复核
* (最后一条 import 在第 80 行,而第 63 行已是 `const NAV_MATERIAL_OF`)。
* 此处原先写的是"由 pi 实测" —— 那句话不准确:是本机**某个** pi 会话/别人测的,
* 我无法独立复核"是谁",这类**归属断言**和"锚短哈希"同族(复核方没法复现"谁做的"),
* 所以改成只陈述**可复核的事实**:错误存在、在哪个提交、怎么复核。
*
* ★ 表留在页面里:`BlurStyle` 是 SDK 枚举,只有 `.ets` 里在作用域内;而
* `model/Appearance.ts` 是**纯逻辑、零 `@ohos` 依赖**,判据要靠 node 直接跑它。
* 分工:**分档判断**在纯逻辑层(可判),**名字 → 枚举**这一步在这里(对着 SDK 写)。
* 那张表和它的 import 后来都随"导航条改回固定档"一起删了(见下面 `NavBar` 的注释);
* 这条注释留在 **import 区**而不是跟着表走,因为要守的是"import 在最前"这个位置本身。
*/
const NAV_MATERIAL_OF: Record<string, BlurStyle> = {
'COMPONENT_THIN': BlurStyle.COMPONENT_THIN,
'COMPONENT_REGULAR': BlurStyle.COMPONENT_REGULAR,
'COMPONENT_THICK': BlurStyle.COMPONENT_THICK
};
import { CalendarPage } from './CalendarPage';
import {
NAV_BAR_BOTTOM,
@ -1711,7 +1709,7 @@ struct MainPage {
* ★ 半径直接用服务端给的那个 px 值:WebUI 就是 `blur(var(--bg-blur))`,
* 两边**同一个物理量、同一个数** ⇒ 这一处不需要映射表,也不该有。
* (`blurStyleFor` 那张表服务的是**材质档**,与这里的 px 半径不是一回事;
* 它的调用点在导航条那条链上 —— 经 `navMaterialFor` 复用,见 `NavBar`。)
* 它是**纯逻辑层**的可判依据;页面侧的面板材质走 `Theme.navMaterial`,见 `NavBar`。)
*/
.blur(this.bgPlan.blurPx)
// 压暗用**系统遮罩色** + 服务端给的浓度:换向(浅色洗白/深色压黑)由系统负责
@ -1793,23 +1791,32 @@ struct MainPage {
* 深浅两套颜色与模糊半径都由系统按主题给。
*/
/*
* 导航条的**面板材质**:**固定系统档**(`Theme.navMaterial`),**不跟随 `bg_blur`**。
* 导航条的**面板材质**:**固定系统档**(`Theme.navMaterial` = `COMPONENT_THICK`),
* **不跟随 `bg_blur`**。
*
* ★ 我一度把它接过用户偏好(`blurStyleFor(blurPx)`),**是错的**,pi 抓出来了。
* 两条依据:
* ① WebUI 侧导航条的糊度**不由 `--bg-blur` 驱动** ——
* `index.css:1114` 的 `.narrow-nav` 是硬编码 `backdrop-filter: blur(18px) saturate(1.5)`
* (`html[data-bg='on']` 作用域内),壁纸糊到 0,导航条照样是玻璃。
* 跟随用户偏好是**新增差异**,不是对齐。
* ② 更根本的:我上一笔刚把"**图片内容模糊**"与"**面板材质**"论证成两个不同的物理量
* (见壁纸层那段注释与 `harmony-appearance.test.mjs`),转头却把**面板材质**的档位
* 接到了**壁纸模糊**这个输入上 —— 自己打自己。两个量、两个输入。
* ⇒ 用户把模糊滑杆拖到 0(要壁纸清晰)时,导航条**仍然**是玻璃。
* 这曾是真实缺陷:滑杆 `min: 0` 可达,`blurStyleFor(0) === 'NONE'`,
* 于是导航条一点材质都没有(本文件里那句「NONE 等于没有材质,"玻璃"就名存实亡」
* 说的正是这件事)。判据 `harmony-nav.test.mjs` 现在钉"可达输入上该档**非 NONE**"。
* ── 这里曾经"说的和做的不一致",记下来(pi 2026-09-15 抓到的)──
* 我一度把档位接过用户偏好(`navMaterialFor(this.bgPlan.blurPx)` 查表),
* 但**注释留在了更早那一版**:那段注释论证的是"固定档"、还写着"跟随是错的"。
* 于是**注释说 (a)、代码是 (b)** —— 下一个读者会照注释把代码改回去,
* 而且他会引我那句"pi 抓出来了"当权威。**说的与做的不一致、而判据看不见**,
* 正是这一路反复在消的形状,这次落在注释上(而注释正是"理由要写清"那条纪律的证据源)。
*
* ── 为什么最终是固定档(pi 的裁定,五条依据,我原先的理由被推翻)──
* ① WebUI 的 `.narrow-nav`(`index.css:1114`)是**硬编码** `backdrop-filter: blur(18px)`,
* **不读** `--bg-blur`;
* ② WebUI 那个滑杆的语义是"**背景**"(`BackgroundPicker.tsx:183`:`label="模糊"`、
* `hint="虚化细节,避免背景与正文抢注意力"`,`min=0 max=24`),只作用在
* `.app-backdrop{filter:blur(var(--bg-blur))}` 上;
* ③ WebUI 自己留了**分开的**令牌 `--bg-blur-panel`(`index.css:267`,注释写明
* "与壁纸自身的 `--bg-blur` 分开:那层给照片打底,这层给面板")——
* 它的词汇表本身就把两者分开;
* ④ **我原先的理由不成立**:我说"(a) 会让那个滑杆在导航条上变成死控件",
* 可那个滑杆**已经**被壁纸消费了(本文件下面的壁纸层把 `bgPlan.blurPx` 交给 `.blur(...)`)——
* 它从来**不是**导航条的控件,(a) 之下它照样是活的;
* ⑤ §7.12 的「材质(玻璃)」行原本写的就是固定档 ⇒ (a) 是**回到**已登记契约。
* 产品向还有一条:**导航条是 chrome,材质应当稳定**,不该因为用户换了一张壁纸而变厚变薄。
*/
.backgroundBlurStyle(NAV_MATERIAL_OF[navMaterialFor(this.bgPlan.blurPx)] ?? Theme.navMaterial)
.backgroundBlurStyle(Theme.navMaterial)
}
build() {