From b16d07b6259adca8e41bb67100e04d0eb501345c Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sun, 20 Sep 2026 05:45:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E5=81=87=E7=BA=A2=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20`Motion.dur(...)`=20=E5=8C=85=E4=B8=80?= =?UTF-8?q?=E5=B1=82=E5=B0=B1=E8=AE=A9=20`paneRiseIn`=20=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=95=BF=E6=96=AD=E8=A8=80=E5=A4=B1=E9=85=8D=EF=BC=88pi=20?= =?UTF-8?q?=E6=8A=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pi `7d98245a` §三 报的形状,我**独立复现并量了两棵树**(隔离 worktree,同刻对照): A 干净 HEAD ⇒ 19 tests / 18 pass / **1 fail**(not ok 16,设备条) B HEAD + 那份未提交的无障碍改动 ⇒ 17 pass / **2 fail**(多出来的正是 `not ok 8`) `Theme.paneRiseIn()` 现在写成 .animation({ duration: Motion.dur(Theme.durRise), curve: Theme.easeRise }) 而 `harmony-nav.test.mjs:441` 是 `/duration:\s*Theme\.durRise/` —— 要求 `duration:` 与 `Theme.durRise` **紧邻**,中间多一层 `Motion.dur(` 就失配。 语义上 `durRise` **仍被引用**(`Motion.dur(x)=reduced()?0:x`,只在系统开"减少动效"时折成 0) ⇒ **假红**。 ★ 放宽的**只是"中间能不能多一层卷绕",判据的区分力一点没动**(3 个方向实测): /duration:\s*(?:Motion\.dur\()?Theme\.durRise/ ① `Motion.dur(Theme.durBase)`(换令牌) ⇒ 仍红 ✓ ② 裸 `Theme.durBase`(包一层来蒙混) ⇒ 仍红 ✓ ③ 干净 HEAD 形状但换令牌 ⇒ 仍红 ✓ 且下面那条 `!/Theme\.durBase/` **逐字仍在**、扫的是**整个函数体** ⇒ 放宽的是**包装**,不是**令牌**。 修后:主树 `18 pass / 1 fail`(只剩 not ok 16 那条设备条); 全套 `red 5 → **4**`(`harmony-nav` 从红名单里出去了,其余 4 条红都是别的会话的)。 ★★ 顺带量出一条**我认为更值钱**的:无障碍层**零判据**(pi §三 的另一半,我确认) · `client/electron/test/` 里 `isAnimationReduceEnabled` / `Motion.dur` / `Motion.reduced` grep **各 0 次**;对照 WebUI 侧 `animation-audit.test.mjs:112` **有** reduced-motion 判据。 · **pi 的变异我复现了**:把 `Motion.dur` 改成恒 `return want`(整个无障碍开关失效, 源里 6 处受影响)⇒ `harmony-nav` 失败集合与变异前**逐条相同**(`17/2`)⇒ **零反应**。 · ★ 而我还量到一个 pi 没说的:**11 个真·动画时长站点里有 5 个绕过开关** —— `CalendarPage.ets:373,410`、`MainPage.ets:2607,2845,2884` 都是裸 `Theme.durX`, 只有 6 处走了 `Motion.dur(`。即"收成一个入口"这个设计意图**目前只落了一半**。 ⇒ 这一半我**没有**加判据也没改源码:`Motion.ets` **尚未被 git 跟踪**, 对它写判据会让 HEAD 立刻变红(那是别人未完成的在制品,不是我的改动范围)。 已把精确读数报给 pi,由落 `Motion.ets` 的那次提交去补判据。 --- client/electron/test/harmony-nav.test.mjs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/client/electron/test/harmony-nav.test.mjs b/client/electron/test/harmony-nav.test.mjs index 952cf08..35420e2 100644 --- a/client/electron/test/harmony-nav.test.mjs +++ b/client/electron/test/harmony-nav.test.mjs @@ -438,9 +438,27 @@ test('★ 窗格切换有真的过场动画(transition 挂在会换的那棵 const riseBody = /paneRiseIn\(\):\s*TransitionEffect\s*\{([\s\S]*?)\n \}/.exec(theme); assert.ok(riseBody, '要能取到 paneRiseIn() 的函数体(它必须是这个方法,形状别改)'); const body = riseBody[1]; - assert.match(body, /duration:\s*Theme\.durRise/, + /* + * ★★ 允许外面再包一层 `Motion.dur(...)`(dsh 2026-09-20,pi 报的假红)。 + * + * 原来这里是 `/duration:\s*Theme\.durRise/` —— 要求 `duration:` 与 `Theme.durRise` + * **紧邻**。而 `Theme.paneRiseIn()` 现在写成 + * .animation({ duration: Motion.dur(Theme.durRise), curve: Theme.easeRise }) + * `Motion.dur(x) = reduced() ? 0 : x`(无障碍:系统开了"减少动效"就折成 0ms)。 + * ⇒ **语义上 `durRise` 仍被引用**(只是多了一层),而正则失配 ⇒ **假红**。 + * 实测(隔离 worktree,同刻对照):干净 HEAD `19 tests / 18 pass / 1 fail`(这条 **not ok 8**), + * 加上那份未提交的无障碍改动后 `17 pass / 2 fail` —— 多出来的正是这条。 + * + * ★ 放宽的**只是"中间能不能多一层卷绕"**,判据的**区分力一点没动**: + * · 仍要求字面量 `Theme.durRise` 出现(`durBase` 依旧不匹配); + * · 下面 `!/Theme\.durBase/` 那条**逐字仍在**,且它扫的是**整个函数体** + * ⇒ `Motion.dur(Theme.durBase)` 这种"包一层来蒙混"**照样红**。 + * (即:放宽的是**包装**,不是**令牌**。混起来的写法不会因为这次放宽而漏。) + */ + assert.match(body, /duration:\s*(?:Motion\.dur\()?Theme\.durRise/, '★ `paneRiseIn` 里入场时长必须引用 `Theme.durRise`(= WebUI rise-in 的 150ms)。' + - '写成 `Theme.durBase` 是拿“壁纸淡入的时长”当“面板入场的时长” —— 正是 2026-09-18 修的那个 bug。'); + '写成 `Theme.durBase` 是拿“壁纸淡入的时长”当“面板入场的时长” —— 正是 2026-09-18 修的那个 bug。' + + '(外面允许包一层 `Motion.dur(...)`:那是无障碍动效开关,包了也仍是在引用 `durRise`。)'); assert.match(body, /curve:\s*Theme\.easeRise/, '★ `paneRiseIn` 里曲线必须引用 `Theme.easeRise`(= rise-in 那条 0.22,0.61,0.36,1)。' + '写成 `Theme.easeOutSoft` 是**另一根**曲线(那是给 transition 用的)。');