diff --git a/client/electron/test/cross-client-theme.test.mjs b/client/electron/test/cross-client-theme.test.mjs index c7d7b27..6a92581 100644 --- a/client/electron/test/cross-client-theme.test.mjs +++ b/client/electron/test/cross-client-theme.test.mjs @@ -1318,7 +1318,7 @@ test('C|「会跟随主题翻转的 Resource」不得当前景色(含矛盾 }); -test('★ 设备:深色下短文本必须都读得动(扫一屏,不只查一个元素)', async (t) => { +test('★ 设备:当前主题下短文本必须都读得动(扫一屏,不只查一个元素)', async (t) => { /* * ★★ 这条是上面"品牌色真的画成那个色"的**一般化**。 * @@ -1357,16 +1357,22 @@ test('★ 设备:深色下短文本必须都读得动(扫一屏,不只查 await new Promise((r) => setTimeout(r, 1500)); /* - * ★ 只在**深色**下判。浅色下这些令牌本来就是为浅底配的, - * 量它们没有信息量(也不会红),但会拖慢判据。 + * ★★ 两个主题**都要判**(第一版只判深色,理由写的是"浅色下这些令牌本来就是 + * 为浅底配的,量它们没有信息量" —— **那个理由是错的**)。 + * + * 切到浅色复扫才发现的实例:浅色 `textSubtle` = `rgb(153,153,153)` 压白底 + * = **2.85:1**,而 WebUI 浅色的 gray-400 是 4.83:1。 + * ⇒ "浅色下没问题"是我自己推的,不是量出来的。 + * + * ★ 纪律:**色令牌的可读性是两个主题各自的事**,不能只验一半。 + * 现在把当前主题**记下来**,两个主题都扫;判据只看"有没有低对比", + * 不关心是哪个主题(两种都是错)。 */ - const img0 = D.readPixels(await D.screenshot(hdc, '/tmp/dark-legibility.png')); + const img0 = D.readPixels(await D.screenshot(hdc, '/tmp/theme-legibility.png')); assert.ok(img0, '要能截屏并解码'); const corner = img0.at(4, 4); const isDark = corner && corner.r < 128 && corner.g < 128 && corner.b < 128; - if (!isDark) { - return t.skip(`当前不是深色主题(左上角像素 rgb(${corner?.r},${corner?.g},${corner?.b}))—— 本条只在深色下有意义`); - } + const themeName = isDark ? '深色' : '浅色'; const lum = (c) => { const f = (v) => { const x = v / 255; return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; }; @@ -1467,7 +1473,7 @@ test('★ 设备:深色下短文本必须都读得动(扫一屏,不只查 '太少说明遍历或尺寸过滤写错了,那样下面的检查恒绿。'); assert.deepStrictEqual(bad, [], - `★ 深色下这些文字读不动(对比度 <3:1):\n ${bad.join('\n ')}\n` + + `★ ${themeName}主题下这些文字读不动(对比度 <3:1):\n ${bad.join('\n ')}\n` + ' 深色下品牌色/面色都要换深色变体:\n' + ' · 文字/图标用 `Theme.accentFor()`(深色自动给 `#80AFF9`,' + '对齐 WebUI 的 `.dark --c-blue-600`)\n' + diff --git a/client/harmony/entry/src/main/ets/common/Theme.ets b/client/harmony/entry/src/main/ets/common/Theme.ets index ad3b2bd..fe8b865 100644 --- a/client/harmony/entry/src/main/ets/common/Theme.ets +++ b/client/harmony/entry/src/main/ets/common/Theme.ets @@ -108,7 +108,23 @@ export class Theme { * 同一条纪律:**别在页面里自己写 `isDark ? a : b`**。 */ static textSubtleFor(dark?: boolean): Resource { - return Theme.isDarkNow(dark) ? Theme.textMuted : Theme.textSubtle; + /* + * ★★ 2026-09-19 **浅色也要换**(第一版只改了深色,漏了另一半)。 + * + * 切到浅色主题复扫,立刻抓到 12 处: + * 浅色 `textSubtle` 实测 `rgb(153,153,153)` 压白底 = **2.85:1** + * 而 WebUI 浅色的 gray-400 是 `rgb(107,114,128)` = **4.83:1**, + * gray-500 是 `rgb(90,98,112)` = **6.15:1**。 + * + * ⇒ 系统三级色**两个主题下都不够**,不是"只有深色有问题"。 + * 同一档位在 WebUI 那边两套主题都做了可读性适配, + * 而系统语义色只管"比二级更淡"这层关系。 + * + * 所以两个主题都返回二级色(`textMuted`)。 + * ★ 为什么不各写一个手写值:系统二级色本身就是"次要文字", + * 语义对得上,且**跟随主题**(不必再维护两个常量、不必登记)。 + */ + return Theme.textMuted; } // ─────────────── 遮罩与材质:交给系统 ───────────────