dsh-background-by-model 0.7.10 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -90
- package/CHANGELOG.zh.md +76 -86
- package/README.md +87 -124
- package/README.zh.md +94 -131
- package/package.json +2 -1
package/CHANGELOG.zh.md
CHANGED
|
@@ -1,129 +1,119 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
-
> 这里保留完整的历史记录;[README.zh.md](./README.zh.md#近期优化) 的「近期优化」一节只列最近两个版本(v0.
|
|
3
|
+
> 这里保留完整的历史记录;[README.zh.md](./README.zh.md#近期优化) 的「近期优化」一节只列最近两个版本(v0.8.0 / v0.7.10)。
|
|
4
4
|
|
|
5
|
-
## v0.
|
|
5
|
+
## v0.8.0
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- **构建产物在打包时生成,而不是提交进仓库** —— `lib/` 是每次发版约 1 MB 的生成代码,也几乎就是这个仓库增长的全部;而让它和 `src/` 保持一致,是件得靠人记住的事。这里没有 `prepublishOnly` 钩子,所以过期的那份会静默发出去,两条流程里没有任何一步会发现。现在它被 `.gitignore` 挡住、由 `prepack` 生成 —— npm 在 `npm pack` 和 `npm publish` 时都会跑它,所以发出去的永远是从被打 tag 的那份源码构建出来的。装包的人这边没有任何变化:还是那三个文件,只是早一分钟才构建出来。
|
|
8
|
+
- **`github:` 安装这条路没了,这是刻意的** —— `dsh plugin --profile web add github:HarmlessFunny/dsh-background-by-model` 拉到的树里已经没有 `lib/`,也没有任何东西会去构建它,所以它只会装出一个加载不起来的插件。现在只剩 npm 一个来源,`npx` 那条也跟着它走;第三种方式(从源码跑一份工作副本)则把「必须先构建」摆在了最前面。
|
|
9
|
+
- **发版改由 GitHub Actions 走 OIDC 完成,于是版本带上了构建 provenance** —— npm token 彻底退出发版路径,npm 会给每个版本附上一份 provenance 证明,把它绑到产出它的那个提交和工作流上。到 v0.7.10 为止的每一个版本都是手动传上去的,什么都不能声称;从这一版起它们是可以核对的,而不只是被声明。
|
|
10
|
+
- **README 和这份文件都收回到 v0.3.x 那批条目的密度** —— 每个功能一句话带过,十道检查各一行,常见问题十五个一个不少、答案砍到承载事实的那一句。用户需要的东西一样没少;去掉的是「每个改动是怎么被想出来的」那部分叙述。
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
## v0.7.10
|
|
10
13
|
|
|
11
|
-
-
|
|
14
|
+
- **节日画的缓存现在按插件所钉的发行版做键,于是更新过的插件拿到的是重新下载,而不是上一代的字节** —— 缓存住在 `holiday-cache/<asset>`,而 `readHolidayAsset` 只要那个文件存在且是一张合法图片就直接拿它作答:不比版本、不联网、不留日志。于是把一个构建指向 assets 仓库的新发行版,改变的是它本会去取的 URL,而实际返回的东西一点没变。现在 `holidayCachePath` 带上了 tag(`holiday-cache/v0.1.0/mid-autumn.webp`),发行版成了文件身份的一部分:钉了新 tag 的构建看的是一个没人写过的目录,更新之后遇到的第一个节日是一次缓存未命中,而 `ls holiday-cache/` 能回答这张盘上留着哪几代。
|
|
15
|
+
- **被取代的那一代会被清掉,而且是在新图落盘之后、绝不在之前。** 光有带版本的键会让每一代永远留在那里 —— 每代约 730 KB,还包括后续发行版已经不再发布的素材。`pruneHolidayCache` 在一次成功的缓存写入末尾运行,删掉名字不是本构建 tag 的代号目录,所以一个取不到的发行版不会让用户丢掉他已经有的画。它是尽力而为,`resetStore` 依然不动任何一代。
|
|
16
|
+
- **门禁** —— `check:node` 的两条 URL 断言与缓存路径现在都读同一个 `REF`,并钉住:所钉那一代里缺失的素材会被重新下载而不是读到旧的、被取代的那一代在新图落盘后消失、正在用的那一代不被碰到。`pnpm test` 十道全过。
|
|
12
17
|
|
|
13
18
|
## v0.7.9
|
|
14
19
|
|
|
15
|
-
- **所有素材引用都钉到 assets 仓库的同一个发行 tag(`v0.1.0`),此前漂开的三处现在一致了** —— README
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
- **推荐配置是刻意放弃「不发版就能修」的** —— 它此前跟着分支,因为它要求不可变的理由和节日素材正好相反:推荐配置的失败是**响亮的**(用户正盯着那个按钮,会拿到一个点名缺哪个槽位的错误),而节日是在没人盯着的那一天静默失效;所以钉版本在这里什么都买不到,而分支买到了「改一个 JSON 就能修好一个不好的推荐」。现在把这个交易换掉了。分支同时还买来了「插件的字节可能在用户装上之后、点下去之前发生变化」;现在一个 tag 同时覆盖截图、节日素材和这份配置,所取的每一个字节都不会再这样。代价是写明的而不是等着被发现的:改一个 JSON 现在要花一个 `assets` 里的 tag、`src/index.ts` 里的一个新值,以及一次 npm 发版 —— 而 tag 不是 commit。它**可以**被重新指向,而 jsDelivr 把版本引用按不可变处理,所以重新指向要发一次 purge 请求而不是 push,于是「修正」的形态是发一个新 tag,而不是强推旧的。这也正是 `presetKey` 在这次改动后仍然保留的原因:一个没清过缓存的边缘节点仍然会回同一个 URL 的上一次字节,所以两次取「这份配置」依然不保证是同一个修订,恢复下载的那一次不能把两个修订拼在一起。
|
|
20
|
-
|
|
21
|
-
- **门禁** —— `check:node` 里有两条断言钉的是旧设计,而它的 `revision()` 辅助函数根本看不见 tag:它匹配的是 40 位 SHA,而这也正是 raw 镜像的引用当年能不靠 `@` 被取出来的唯一原因。现在它从仓库名旁边匹配(jsDelivr 形状是 `HarmlessFunny/assets@<ref>`,raw 形状是 `HarmlessFunny/assets/<ref>/`),于是两个镜像仍然可以互相比较;两条断言都要求 `v0.1.0` —— 节日素材那条变成「pinned to the assets release tag, never to a branch」,推荐配置那条变成「read at the assets release tag, not at a branch」,取代了此前**故意**钉住分支的那一条。`pnpm test` 十道全过,`lib/` 就是那一次运行的产物。
|
|
20
|
+
- **所有素材引用都钉到 assets 仓库的同一个发行 tag(`v0.1.0`),此前漂开的三处现在一致了** —— README 的截图读 `main`,节日素材钉的是一个原始 commit 哈希(`HOLIDAY_ASSETS_COMMIT`),推荐配置是刻意跟着 `main` 的:三处引用,对「这个构建在看哪一份字节」给出三种答案。现在是 `HOLIDAY_ASSETS_REF = 'v0.1.0'`,`PRESET_ASSETS_REF` 用同一个字符串,于是 `HarmlessFunny/assets` 的一个发行版就是插件所取的每一个字节的同一个版本 —— 节日素材、推荐配置和 README 的图片一起 —— 而且这个值人能读、能拿去和 GitHub 上的 tag 对照、也能在一处改完。
|
|
21
|
+
- **节日素材的字节并没有跟着改名而变。** `58a9e107` 是 `v0.1.0` 的祖先,两张 `holiday/*.webp` 在这两个修订之间逐字节相同,所以下载还是同一次下载。真正变了的是 raw 镜像也带上了 tag,这才让「两个镜像服务同一个修订」是按值成立、而不是靠约定。
|
|
22
|
+
- **推荐配置是刻意放弃「不发版就能修」的** —— 它此前跟着分支,因为它要求不可变的理由和节日素材正好相反:推荐配置的失败是响亮的(用户正盯着那个按钮),而节日是在没人盯着的那一天静默失效。这就是换掉的东西:改一个 JSON 现在要花一个 `assets` 里的 tag、`src/index.ts` 里的一个新值,以及一次 npm 发版。而 jsDelivr 把版本引用按不可变处理,重新指向一个 tag 要发 purge 请求而不是 push —— 这也正是 `presetKey` 仍然保留的原因:一个没清过缓存的边缘节点仍然会回同一个 URL 的上一次字节。
|
|
23
|
+
- **门禁** —— `check:node` 的 `revision()` 辅助函数匹配的是 40 位 SHA,根本看不见 tag;现在它从仓库名旁边匹配(`assets@<ref>` 与 `assets/<ref>/`),于是两个镜像仍然可以互相比较,两条断言都要求 `v0.1.0` 而不再钉分支。`pnpm test` 十道全过。
|
|
22
24
|
|
|
23
25
|
## v0.7.8
|
|
24
26
|
|
|
25
|
-
- **新装打开的就是一条空白规则,而不是「还没有规则」那一屏** ——
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
- **推荐配置的下载按文件重试,而且失败的那一次会把已经下到的部分留给下一次** —— 此前一个文件只有两次机会(两个镜像各一次),七张壁纸里第六张碰上一次 502、一次连接被重置或者一次 CDN 抽风,前面六张就白下了,而用户唯一的办法 —— 再按一次按钮 —— 是从零开始。现在每个文件最多三轮、轮与轮之间先等 400 ms 再等 800 ms(`src/preset.ts` 的 `PRESET_ATTEMPTS` / `presetRetryDelayMs`),而且失败的那一次会把已经拿到的字节留在那里(`presetHeld`):下一次按按钮先重新取 manifest 与 config(两个小文件),只有当这份 config 与那些字节来自的那一份**逐值相同**时才复用(`presetKey`,把对象键排序后的规范形式 —— 上游把键顺序重建过一遍不该白白丢掉这些字节),于是「第六张失败」从重下七张变成只重下一张。三种失败**不重试**,每一种都有自己的理由:404/403 是「这个文件不在那儿」(配置跟随的是分支,作者改个文件名就必须**快**而响地报到槽位上,而不是再等两轮)、超限是「字节本身就是问题,下一轮还是这些字节」、超时是「六十秒的沉默不是天气」(两个镜像在同一轮里都已经问过了,而这一条正是把单个文件的最坏情况钉在三分钟而不是六分钟上的东西:两个镜像都不吭声的那一轮当场就结束,也就是原来那两分钟;只有「一个镜像沉默、另一个是瞬态失败」混在一起的那一轮,才会把一分钟带进下一轮)。**严格性一个字没改**:第一个拿不到的文件仍然让整次尝试失败、仍然报出槽位名 —— 变便宜的只是重试,不是失败。按钮上那个计数现在描述的是**整份配置**而不是这一次的传输,所以续传的那一次从 6/7 开始、到 7/7 结束(这也是这次改动**没有**碰界面任何一处的原因)。节日素材刻意**没有**跟着改成多轮:它是在启动时、当天第一次绘制之前抓的,一轮的等待会直接加到首帧上 —— 而它有缓存,此后每一次读取都会再试一次,按钮却没有「此后再读一次」这回事。
|
|
30
|
-
|
|
31
|
-
- **门禁** —— `pnpm test` 现在是**十道**(新增 `check:preset`)。`check:node` 新增:空数据目录读出来正好一条规则、那条规则是空的(无匹配串、无颜色、无图)、它是规则 1(因此兼任兜底)、显式写空的规则列表读回仍然为空(这几条就是新装那条规则的形状,以及那条不该被种回来的区分);`resetStore` 之后那条断言改成同一语义 —— 它原来钉的正是旧行为(「读到一个空配置」)。重试本身按**请求数**钉住:两个镜像同时 503 一次时,同一个文件被再问一遍并最终拿到(日志里三行:jsDelivr、raw、又是 jsDelivr)、托管处没有的文件仍然只花两次请求(每镜像一次、不等待)、永久 500 的镜像总共只花六次请求(三轮 × 两个镜像 —— 重试是有预算的)。`check:ui` 新增第 6 节:UI 里每一个 `var(--dsw-…)` 都必须是已安装主题确实发布过的 token —— 读不到主题(peer 依赖不在)时这一节跳过并说明,因为那是关于这台宿主的事实,不是关于这个仓库的;这一类失败本来不会在任何地方报错,声明被丢掉、属性悄悄回落到继承值,只有人眼看出来不对。新的 `check:preset` 钉住策略本身与两侧的接线:六个失败原因各自「值不值得再问一次」(三个终态正是能在本地廉价判定的那三个,而超时之所以不重试是因为同一轮里两个镜像都已经问过)、等待指数增长且有上限、`presetKey` 对同一个值的不同键顺序给出同一个键(而图片列表的顺序**算数**,因为它就是轮换顺序)、续传拿到的是副本而不是那条记录本身、以及两侧真的在用这些判定 —— node 半边循环轮次并按策略决定要不要再来一轮、客户端按「还缺哪些」而不是整个槽位表来铺并发池、失败时把已下到的字节留成 `presetHeld`、成功时清掉、以及体积上限**在文件被收下之前**判定(收下之后再判的话,超限的那一次会把每个槽位都留在手里,下一次续传于是无文件可抓、直接把一份超限的配置放行)。
|
|
27
|
+
- **新装打开的就是一条空白规则,而不是「还没有规则」那一屏** —— 完全没有配置文件时 `migrateLegacy` 返回 `rules: []`,而 `normalizeConfig` 把那个空数组当成「用户把规则删光了」。现在只有「`rules` 这个键根本不在」才意味着「从未配置过」,它换来一条空白规则 —— id 是 `r1`,所以它在面板上就是规则 1、就是兜底、就是默认选中的那张卡。键在、数组是空的,仍然是用户主动删光的结果,保持为空。规则工厂挪进了 `src/schema.ts`(`blankRule`),出厂配置、sanitizer 与客户端的「新增规则」共用它。
|
|
28
|
+
- **placeholder 不是「挑亮了」,是那条声明从来就没生效** —— `--dsw-alias-label-quaternary` 在整个 harness 主题里一个定义都没有,声明在计算值阶段被丢掉,于是 placeholder 回落到 `inherit`,拿到输入框自己的 `label-primary`。现在三个带 placeholder 的输入统一读 `--dsw-alias-label-caption`,也正是 `PLACEHOLDER_RULE` 早就给输入框用的那个 token。同一个死名字还有两处:`.dab-brand-tag` 那个死别名,以及 `.dab-pick-n` 的 `--dsw-mono`(插件自己的变量是 `--dab-mono`)。
|
|
29
|
+
- **推荐配置的下载按文件重试,而失败的那一次会把已经下到的部分留给下一次** —— 此前一个文件只有两次机会(两个镜像各一次),七张壁纸里第六张碰上一次 502,前面六张就白下了。现在每个文件最多三轮、先等 400 ms 再等 800 ms,失败的那一次把已经拿到的字节留下,只有当 config 与那些字节来自的那一份逐值相同(`presetKey`)时才复用。404/403、超限、超时三种不重试,各有各的理由。严格性一个字没改 —— 第一个拿不到的文件仍然让整次尝试失败、仍然报出槽位名 —— 而按钮上那个计数现在描述的是整份配置,所以续传的那一次从 6/7 开始。
|
|
30
|
+
- **门禁** —— `pnpm test` 现在是十道(新增 `check:preset`)。`check:node` 钉住新装那条规则的形状、以及「显式写空的列表不会被种回来」的区分,并按请求数钉住重试本身:一次瞬态 503 三行日志、托管处没有的文件两次请求、永久损坏的镜像六次。`check:ui` 新增一节,要求 UI 里每一个 `var(--dsw-…)` 都是已安装主题确实发布过的 token,读不到主题时跳过并说明。
|
|
32
31
|
|
|
33
32
|
## v0.7.7
|
|
34
33
|
|
|
35
|
-
- **新装出来就是作者本人那套外观,而且不用联网** ——
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
- **节日开关出厂是关的** —— 第一次装上只画模型规则说的东西,别的什么都不画;「配置」页那一个开关才是「要这个功能」的表达方式。它此前是开的,理由是「这个功能的意义就在于到日子背景自己换」;那个理由对于一份**已经被人选定的**配置是对的 —— 所以推荐配置仍然把它**打开** —— 但对于一个刚装上、自己还没有任何壁纸的插件不对:中秋当天,新用户看到的第一样东西会是一张没人要的节日图。净化规则也从「只有显式的 `false` 才关掉」改成「真正的布尔值算数,其它一律取出厂默认」:功能出现之前写下的配置里那个缺失的字段、以及手改出来的垃圾值,现在都意味着关。块内每个节日各自那个开关没动 —— 那是一个已经打开的功能内部的细节,不是这个开关本身。
|
|
40
|
-
|
|
34
|
+
- **新装出来就是作者本人那套外观,而且不用联网** —— 「界面」页的出厂默认值现在**就是** `preset/theme-config.json` 里那套数字:主背景 `0%`、左侧栏 `10%`、右侧栏 `45%`、卡片 `100%`、代码块 `81%`、输入框与控件 `88%` 外加 `60 px` 模糊、设置面板 `100%`、对话文本框 `35%`、轨迹页 `73%`。这些数字此前每一个都是按「安全」而不是按「好看」逐项挑的,这就是为什么以前新装打开的是一个宿主的苍白近似。这些常量住在 `src/schema.ts`,旁边写着它们是从真实数据目录抄出来的那一份。
|
|
35
|
+
- **`rightbarOpacity` 保留了它「从未被拥有」的状态,而新装出来是已被拥有的** —— 预览栏的 `null` 意思是「跟随 `opacities.bg`」,而此前每一个版本都写过它,因为用户从没拖过的那一栏落盘就是显式的 `null`。所以 `normalizeRightbarOpacity` 只有「这个键根本不在」才给出厂的 `45%`;把 `null` 当成缺失,会把每一份「预览栏正跟着主背景」的既有配置悄悄重画。
|
|
36
|
+
- **节日开关出厂是关的** —— 第一次装上只画模型规则说的东西,别的什么都不画,「配置」页那一个开关才是「要这个功能」的表达方式。推荐配置仍然把它**打开**。净化规则改成「真正的布尔值算数,其它一律取出厂默认」:功能出现之前写下的配置里那个缺失的字段、以及手改出来的垃圾值,现在都意味着关。
|
|
41
37
|
- **「界面」页每张卡片上那个百分比胶囊删掉了** —— 那个数字本来就在它正下方的滑块行上,于是卡头又只剩图标和名字,`.dab-part-badge` 连同它的样式规则一起走。
|
|
42
|
-
|
|
43
|
-
- **门禁** —— `pnpm test` 仍是九道;上面这些默认值动到的是 `check:code-plate`(代码块出厂走配置的 `81%`)与 `check:node`,后者的新断言是**按值**写死的,所以「改了常量没改配置、或改了配置没改常量」会直接让一道校验失败,而不是慢慢漂开:完全没有配置文件时读出来的那套外观数字、显式 `null` 的预览栏读回成它自己、它自己的数字被保留、非数字的手改值落回出厂的 `45%`,以及节日开关两个布尔方向加一个非布尔值。
|
|
38
|
+
- **门禁** —— `pnpm test` 仍是九道;上面这些默认值动到的是 `check:code-plate` 与 `check:node`,后者的新断言是**按值**写死的,所以「改了常量没改配置、或改了配置没改常量」会直接让一道校验失败,而不是慢慢漂开。
|
|
44
39
|
|
|
45
40
|
## v0.7.6
|
|
46
41
|
|
|
47
|
-
- **规则页从一摞会自己长大的卡片变成一条选项卡 + 一个编辑器** ——
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
- **一键装上「推荐配置」** —— 「配置」页多了第三张卡,从同一个 [`HarmlessFunny/assets`](https://github.com/HarmlessFunny/assets) 仓库下载作者本人正在用的那套配置并就地覆盖你的。**它托管在数据目录自己的形状里**:`preset/preset.json`(形状闸门)、`preset/theme-config.json`(6.5 KB 可读 JSON)和 `preset/modelbg-<slot>`(每个槽位一个原始文件)。第一版是单个主题文件、所有壁纸内联成 base64,2.9 MB 里 99.8% 是图片 —— 在几十万字符的一行里找一个 `match` 字符串不是任何人能做的手改,格式就是为这个改的;换过来之后,改配置是在 GitHub 上编辑 6.5 KB 的 JSON,换壁纸是替换一个文件,发布是从 `~/.dsh/.dsh-background-by-model-data/` 里 `cp` 一下。node 半边新增 `fetchPresetConfig`(取 manifest 与 config、在**这一侧**跑共享 sanitizer、再从这个配置推导出要请求哪些文件)与 `fetchPresetImage`(按槽位取一个文件,魔数校验后返回 data URL),旧的单文档 `fetchPreset` 删掉;`fetchHolidayAsset` 上一版拆出的通用 `fetchAsset` 被两者复用。**请求清单从配置推导,而不是来自第二份清单**:加一张壁纸就是在 config 里加一条并放进同名文件;反过来说,一份不受信任的配置决定了这个进程会去网络几次,所以每个槽位名都要过 `SLOT_RE`(在 `normalizeImage` 里),数量另有上限。**config 里合法存在的两个节日槽位会被剔掉而不是去请求** —— `holidays.items` 里必然有 `h-midautumn` / `h-nationalday`,而数据目录里永远不可能有 `modelbg-h-*` 文件(上一版刚加的硬断言),照单去请求会让整个功能在一份插件自己保证不存在的文件上失败。客户端**一个文件一个请求**地取、同时最多四路 —— 实测同一份配置顺序取 8.3 秒、并发取 4.8 秒,因为付的是 HTTP/2 上的每请求延迟 —— 按钮上显示 `3/7`;每个文件因此有自己的镜像回退与自己的校验。**少一张就整体失败并报出是哪个槽位**:一份悄悄少了图的配置恰恰是「节日素材钉死 commit」那条契约要防的静默失效,把它报出来才让分支引用在这里站得住。落地仍然走本地文件那条 `applyThemeFile`(在客户端组装成 `exportTheme` 写出的形状),所以版本闸门、sanitizer、清空都还是同一条路;`preset.json` 让版本闸门在请求第一张壁纸之前就能生效。它仍然是这个面板里唯一会销毁东西的操作:下载在**提问之前**(确认框因此能如实说出手里有什么),清空在**下载成功之后**(CDN 不通不该让你在等一份永远没来的配置的路上先弄丢自己的配置),一个旧到写不了这套形状的宿主在删除任何东西之前就被拒绝,`holiday-cache/` 不碰,配置也从不落盘缓存。`check:node` 的桩新增了「按文件名供应一整个目录、缺名就是 404」这一档,覆盖:manifest 与 config 按序取且当场 sanitize、请求清单由规则推导且节日槽位被剔掉、一张壁纸一个请求且类型是嗅出来的、对单个文件回落到 raw、config 点名而托管处没有的文件是一个错误、节日槽位与畸形槽位名在任何请求之前就被拒绝、manifest 版本不是数字、写给更新形状的配置在请求第一张壁纸之前被拒绝、config 不是 JSON / 是数组 / 图片数超限、以及镜像谎报超长。
|
|
54
|
-
|
|
55
|
-
- **发布包从 1.1 MB 瘦到约 220 kB** —— 除了上面那两张节日画,另外两样东西也在占地方,而且都不该由下载这个插件的人来付。**文档截图搬走了**:`example_img/`(三个 webp,220 KB)移到同一个 assets 仓库的 `dsh-background-by-model/` 目录下,两份 README 改用 jsDelivr 绝对地址引用 —— 这个插件此前专门把截图放进 `files` 是为了让 npm 页面上的图不裂,而绝对地址同样做得到,还不用把二进制塞进包里、更不用写进 `.git` 的历史。`screenshots.json` 删掉了:翻遍整个 DSH 安装目录和 `~/.dsh` 都没有任何消费方。**`lib/client.js.map` 不再发布**:它是给浏览器 bundle 用的源码映射,624 KB,对装包的人没有用处,仓库里仍然保留(要调试本地构建的人本来就该对着本地构建调)。10 个文件、约 220 kB packed / 690 kB unpacked,此前是 13 个文件、1.1 MB / 2.0 MB。(这两组数字刻意写成约数 —— 这条记录和两份 README 本身就是这个数字的一部分,每改一次就把它推高一点。这个数字想说的是:图片搬走之后,包里剩下的确实只有代码和文档。)
|
|
42
|
+
- **规则页从一摞会自己长大的卡片变成一条选项卡 + 一个编辑器** —— 每条规则是一个选项卡,页面上只挂载一个编辑器,于是页面高度只跟「一张卡片 + 一条选项卡」有关,与规则条数无关。选项卡把原本只在卡头上才看得到的东西搬了上来:序号、缩略图、匹配串,以及两条不用展开就该知道的状态(是不是当前生效、在轮换还是被关掉);条子横向滚动而不是换行,理由相同。「+」和「切换哪条规则」挪到了滚动区**之外**,因为放在里面时,一个长列表里唯一能新增规则的控件会被滚走。匹配测试器搬到了「资料」页 —— 它回答的正是关于整份配置的问题。选项卡背后那两个判定是纯的,住在 `src/client/rules-view.ts`,由新的 `check:rules` 钉住。
|
|
43
|
+
- **轮换卡片的控件按你的要求重新排了一遍** —— 「下一张」与「正在显示第 2 / 3 张」移出了轮换开关的判定(那句读数是这张卡片上唯一说明当前是哪张图的地方,却跟着开关一起消失);「切换模型时也换一张」挪到顺序那一行,三者都在回答「什么时候换」;「1 小时」从停留时长预设里删掉;那排八个固定色板删掉了,连同它唯一的读者(`state.ts` 里的 `PALETTE` 表与 `.dab-swatch*` 规则);整个轮换块移到第二列、主题色之下,离开折叠成单列时卡片里最糟的那个位置。
|
|
44
|
+
- **节日画不再随包发布:当天按需下载、按素材名缓存** —— 两张节日壁纸(228 KB + 500 KB)占了整个 tarball 的三分之二,为了一张一年只被看一天的画。现在它们托管在 [`HarmlessFunny/assets`](https://github.com/HarmlessFunny/assets),节点半边在节日当天第一次读取时下载、校验、写进 `~/.dsh/.dsh-background-by-model-data/holiday-cache/`。引用钉死在 commit 上而不是分支;`cdn.jsdelivr.net` 主用、raw 兜底,两者指向同一个 revision;下载失败是一个正常状态,所以模型规则继续画;不是图片的缓存条目按未命中处理而不是被信任。缓存仍然按**素材名**命名,刻意放在槽位命名空间之外,所以 `writeImage` 照旧拒绝节日槽位。
|
|
45
|
+
- **一键装上「推荐配置」** —— 「配置」页多了第三张卡,从同一个 assets 仓库下载作者本人正在用的那套配置:`preset/preset.json`(形状闸门)、`preset/theme-config.json`(6.5 KB 可读 JSON),以及每个槽位一个 `preset/modelbg-<slot>` 文件。第一版是单个主题文件、所有壁纸内联成 base64 —— 2.9 MB 里 99.8% 是图片,不是任何人能做手改的文档。请求清单从配置推导而不是来自第二份清单,所以每个槽位名都要过 `SLOT_RE`、数量另有上限;config 里合法存在的两个节日槽位会被剔掉而不是去请求;少一张壁纸就整体失败并报出是哪个槽位。它仍然是面板里唯一会销毁东西的操作:下载在提问**之前**,清空在下载成功**之后**。
|
|
46
|
+
- **发布包从 1.1 MB 瘦到约 220 kB** —— 文档截图搬到同一个 assets 仓库、两份 README 改用 jsDelivr 绝对地址引用(当年把它们放进 `files` 就是为了这个),`screenshots.json` 删掉(没有任何消费方),`lib/client.js.map`(624 KB)不再发布但仓库里仍然保留。10 个文件、约 220 kB packed / 690 kB unpacked,此前是 13 个文件、1.1 MB / 2.0 MB。
|
|
56
47
|
|
|
57
48
|
## v0.7.5
|
|
58
49
|
|
|
59
|
-
- **布局模式属于图片,不属于规则** —— 适应 / 填充 / 拉伸 / 平铺 / 居中
|
|
60
|
-
- **配置格式升到 6,因为这次迁移两个方向都是无声的(修复)** —— schema 5
|
|
61
|
-
- **节日的图按定义就是 填充** ——
|
|
62
|
-
- **渐变只作用于当前调色板真正写入的东西(修复)** ——
|
|
63
|
-
- **代码块跟着调色板走,而且它自己的底板有了独立透明度(修复)** ——
|
|
64
|
-
- **四个小修(修复)** ——
|
|
65
|
-
- **门禁** —— `pnpm test` 现在是**八道**。`check:code-plate
|
|
50
|
+
- **布局模式属于图片,不属于规则** —— 适应 / 填充 / 拉伸 / 平铺 / 居中 此前是每条规则一个值、覆盖一轮轮换里的每一张图,所以一张横构图照片和一张竖屏截图没法各自取景。现在模式存在 `images[].bgMode` 上、从正在画的那张图读回,胶片条下面那排胶囊编辑的也是那里选中的那张图;规则还没有图片时这排胶囊是**禁用**而不是隐藏。README 与 README.zh 里凡是说「模式属于规则」的地方都改了。
|
|
51
|
+
- **配置格式升到 6,因为这次迁移两个方向都是无声的(修复)** —— schema 5 的宿主会按自己认识的键重建每一个图片条目,写进去的逐图模式会在第一次写入时消失;而 schema 6 读一份 schema 5 的配置时**必须**把规则级的值抬到它的每一张图上,否则所有现成壁纸都会掉到默认值。`bgMode` 进了 `LEGACY_RULE_KEYS`,所以它是被刻意消费掉的迁移字段,不该在宿主日志里报成漂移。
|
|
52
|
+
- **节日的图按定义就是 填充** —— 满幅的节日画不该有黑边。模式和它旁边的槽位、颜色一样取定义、不取磁盘,所以手改过的值换不掉节日的模式;旁边的取景仍然是你自己的。
|
|
53
|
+
- **渐变只作用于当前调色板真正写入的东西(修复)** —— 报告是浅色切浅色时白色色块渐变成黑色再跳回白色,白色值量到的是 `237, 243, 254`。这个数字就是答案:`#edf3fe` 是 `--dsw-static-deepseek-50`,宿主**浅色**方案画用户消息气泡用的值,而渐变样式表之所以注册了它,是因为 `fadeTokenNames()` 要的是**深色**分支的 token 表(80 个名字),浅色分支只写其中 35 个。另外 45 个仍然归宿主,而宿主按自己的时间表改它们 —— 触发者还是插件自己,它每次换配色都销毁并重新注册主题。现在作用域的 token 只在**当前调色板**确实写它时才发出,配色深浅没变也不再重建皮肤。
|
|
54
|
+
- **代码块跟着调色板走,而且它自己的底板有了独立透明度(修复)** —— 报告是**浅色**界面里深绿色文字压在近黑色的底板上。宿主的 shiki 表在 `:root` 上声明 `var(--dsw-alias-markdown-code-block)`,而插件(和宿主自己)只在 `body` 上声明这些 token,于是根元素上除了宿主自己的颜色什么也读不到。现在调色板规则对 `:root` 与 `body` 一并发出、`:root` 也加入渐变作用域,底板与 banner 重新是调色板的染色。新增 **`code`** 透明度档位驱动这两块表面,各自读自己的插件自有变量,默认不透明 —— 代码块是拿来读的。
|
|
55
|
+
- **四个小修(修复)** —— 开着轮换把图片删到只剩一张时,开关仍显示「开」而面板在少于两张时把它禁用了,于是也关不掉;现在删图后不足两张就清掉 `enabled`,`normalizeRule` 对不经过面板的路径强制同一条不变量。「切换时长」被印了两遍(一个小节标题,隔一行又是滑块的标签)。资料页页脚的包名与品牌磁贴现在是指向项目仓库的链接,都读 `repo.ts` 里那一个地址,`check:ui` 拿它和 `package.json` 的 `repository` 对比。
|
|
56
|
+
- **门禁** —— `pnpm test` 现在是**八道**。`check:code-plate` 与 `check:image-mode` 加入套件;`check:rotation` 增加开关与数量的不变量,`check:ui` 增加仓库链接一致性,`check:transition` 增加归属规则,`check:repaint` 钉住武装渐变的那两行。
|
|
66
57
|
|
|
67
58
|
## v0.7.4
|
|
68
59
|
|
|
69
|
-
- **弹窗里的控件现在和壁纸走同一个时钟,而不是等它切完再跳(这一条是修复)** ——
|
|
70
|
-
-
|
|
71
|
-
- **修法:过渡表按作用域给,每个元素只拿自己声明的 token** —— `paletteFadeCss` 的输入从 `selectors: string[]` 变成 `scopes: { selector, tokens }[]`:`body`
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
- **门禁** —— `check:transition` 补上了淡入形状的另一半:只带标准属性的作用域照样发规则、该属性与 token 用同一套时长与缓动、属性绝不会被当成颜色去注册、一个未注册的 token 名不再连累同一作用域里的属性、`0` ms 同样解除它。`check:repaint` 补上了配对本身:三块插件自绘的表面必须既由自有变量上色、又有一个点着同一个共享常量的淡入作用域 —— 以后再添第四块而忘了淡入,会是一条失败的门禁,而不是一张没人拍的截图。
|
|
60
|
+
- **弹窗里的控件现在和壁纸走同一个时钟,而不是等它切完再跳(这一条是修复)** —— 换主题色那一下,设置弹窗里的控件会**整整一套切换时长**停在上一套颜色上,直到背景切完才瞬间换成新的。这是从一个真实会话里量出来的:`body` 自己的 token 在那 3 秒里插值正常,而胶囊按钮的实际底色每一次采样都与旧值逐位相同,直到动画结束之后才用一段短过渡到达新色。
|
|
61
|
+
- **卡住的是中间层,不是「继承拿不到动画值」** —— 只继承、自己没有过渡的消费者**逐帧跟随**声明它的那个元素,隔离实验证实了这一点。真正的成因是插件把**整张 token 表**挂到了三个元素上,其中两个只**重新声明**三个 layer token:给一个只继承的 token 挂过渡,该元素的过渡目标就是**武装那一刻它看到的值**,于是它变成一条被阻尼的过渡,整棵子树跟着这份滞后的副本走。
|
|
62
|
+
- **修法:过渡表按作用域给,每个元素只拿自己声明的 token** —— `paletteFadeCss` 的输入从 `selectors: string[]` 变成 `scopes: { selector, tokens }[]`:`body` 拿全表,弹窗与轨迹页根节点只拿它们重新声明的那三个 layer token。这不是「少挂几条」的优化 —— 一个作用域拿到自己没有声明的名字,就是把上面那条滞后复制到整棵子树上。
|
|
63
|
+
- **还有三块在硬切,而且正是那些用插件自己的颜色画的面(这一条是修复)** —— 把中间那帧的每个像素分别与首帧、末帧比对之后,设置弹窗自己那块底板已经在终色上,而它里面的每一张卡片还在首色上。卡片在渐变、底板不渐变,说明走的是另一条上色路径:底板不是用注册过的 alias token 画的,而是用 `--dsh-any-bg-settings-surface`,而**未注册**的自定义属性根本不能插值。同一形状还有两处:文件预览面板与 Cordis 面板。
|
|
64
|
+
- **修法:作用域可以点一个标准属性,且上色规则与淡入共用同一个选择器** —— `PaletteFadeScope` 新增 `properties?: string[]`,与 token 一起排进同一条 `transition`,并且**故意不**按注册名过滤。`fadeScopes()` 里设置弹窗底板与文件预览面板各带一条 `background-color`,Cordis 面板带 `--dsw-specific-menu`;两条上色规则与各自的淡入作用域各读同一个共享常量,上色的那一半和淡入的那一半不可能再走岔。在 Chromium 里拿**真实产出的 CSS** 量过:五块表面每一次采样都处在同一进度 —— t=1500ms 时 80.2%,恰好是 `ease(0.5)`。
|
|
65
|
+
- **顺带记录一个不构成原因的现象** —— 探针还显示那张 fade 表在武装后的一帧左右,被后续一次非调色板 apply 重写成不带 `transition` 的版本,而**已经起跑的过渡不会因为声明被撤掉而中断**。它不是这次卡顿的成因,但它意味着「过渡还没开始」的元素什么都拿不到。
|
|
66
|
+
- **门禁** —— `check:transition` 补上了淡入形状的两半:一个作用域绝不会拿到它只继承的 token、自己什么都没声明的 scope 不发规则、只带标准属性的作用域照样发规则并与 token 用同一套时长与缓动、`0` ms 同样解除它。`check:repaint` 补上了配对本身:三块插件自绘的表面必须既由自有变量上色、又有一个点着同一个共享常量的淡入作用域 —— 以后再添第四块而忘了淡入,会是一条失败的门禁,而不是一张没人拍的截图。
|
|
77
67
|
|
|
78
68
|
## v0.7.3
|
|
79
69
|
|
|
80
|
-
- **切换效果本身成了一个设置:四种效果、一种缓动、一个时长,都在「配置」页上** ——
|
|
81
|
-
- **卡片上带一个预览色块,而它不是装饰** ——
|
|
82
|
-
- **时长只有一个,「跟随每条规则」删掉了** ——
|
|
83
|
-
- **界面配色现在和壁纸走同一个时钟** ——
|
|
84
|
-
- **浅↔深互切是立即切换,而壁纸照旧做动画(这一条是修复)** ——
|
|
85
|
-
- **墨色现在是同步写入的,而那是一个真实存在、且只有一个写入者的 bug(这一条是修复)** ——
|
|
86
|
-
- **配置格式升到 5、导出格式升到 6,旧宿主依旧吃不掉配置** —— schema 4 的 sanitizer
|
|
87
|
-
- **门禁** —— `check:transition
|
|
70
|
+
- **切换效果本身成了一个设置:四种效果、一种缓动、一个时长,都在「配置」页上** —— 这个插件做的每一次换图此前都走同一个写死的交叉淡入,而它的时长读的是一个没有任何控件能碰到的字段。效果是**淡入淡出**、**直接切换**、**缩放淡入**、**平移推入**(后两种只对进来的那一层做 transform,所以一个字节的额外传输都不花);「直接切换」和 `0` 毫秒是同一个硬切,而不是其中一个被读成「没设置」;`0` 是一个被保留的真实取值;系统的「减少动态效果」是**否决**而不是把动画缩短。判定是纯函数(`src/client/transition.ts`),正因如此 `check:transition` 才能钉住那些不会抛错的失败。
|
|
71
|
+
- **卡片上带一个预览色块,而它不是装饰** —— 壁纸淡入它自己是什么都看不见的,所以「在已经在屏的那张图上重放效果」会什么都不显示:这是这个功能唯一可能「明明在工作却看起来坏了」的方式。色块按此刻一次真实切换会用的时长重放选中的效果。
|
|
72
|
+
- **时长只有一个,「跟随每条规则」删掉了** —— 那张卡的默认值是「跟随每条规则」,而它指向 `rotate.fadeMs`:一个从 0.7.0 起就在格式里、却从来没有控件能到达的字段。现在滑块本身就是那个设置,而 `legacyFadeMs` 会在读取一份早于这个设置的配置时,把找到的第一个「有意为之」的值折进全局时长;显式的 `durationMs` 永远胜过它旁边的旧字段。
|
|
73
|
+
- **界面配色现在和壁纸走同一个时钟** —— 这个渐变是**注册**问题而不是声明问题,因为未注册的自定义属性无法插值:`src/client/palette-fade.ts` 会发出把别名令牌变成 `<color>` 的 `@property` 规则,外加一条 `transition`,作用于「自身的声明会随调色板变化」的那些元素。它**只在调色板确实变了**的时候武装,因为拖滑块时挂着一条活着的过渡会让表面跟不上指针;宿主没有公布的令牌是**刻意不注册**的。
|
|
74
|
+
- **浅↔深互切是立即切换,而壁纸照旧做动画(这一条是修复)** —— 在两套调色板之间插值会让整个界面走过中间调,而那里的墨色**两个方向都是错的**,所以渐变只在**配色深浅不变**时武装。这条规则刻意不碰壁纸:一张图淡入另一张图没有「深浅」可以搞错,所以它照旧听切换效果的。
|
|
75
|
+
- **墨色现在是同步写入的,而那是一个真实存在、且只有一个写入者的 bug(这一条是修复)** —— 把一条规则换成深色主题色时,面板的文字可能留在**上一套**调色板上,而所有表面都已经跟到新的那套:深色面板上的深色墨色,读不出来,只有重新加载才能清掉,日志里什么都不会说。其它每个表面都有第二个同步的写入者,所以只有令牌样式表可能变旧,而这唯一的写入者只能从一个包在 `catch {}` 里的 `requestAnimationFrame` 回调到达 —— 不在渲染的窗口会吞掉那一帧,把此后每一次更新都堵在它后面。现在调色板一旦移动就在**与它必须保持一致的表面同一个任务里**同步写入,写入者也会把失败记进日志而不是吞掉。
|
|
76
|
+
- **配置格式升到 5、导出格式升到 6,旧宿主依旧吃不掉配置** —— schema 4 的 sanitizer 会**按自己认识的键重建**配置,所以一个仍在运行的旧宿主进程会在刷新后的第一次写入时丢掉效果、缓动和时长,悄无声息。主题文件升到格式 6;5 及更早仍可导入。
|
|
77
|
+
- **门禁** —— `check:transition` 加入 `pnpm test`,现在是**六道**。`check:repaint` 新增了这个 bug 由之构成的三行,`check:node` 覆盖公布 schema 与旧值折算,`check:ui` 覆盖新文案与两个新类。
|
|
88
78
|
|
|
89
79
|
## v0.7.2
|
|
90
80
|
|
|
91
|
-
- **胶片条自己就是控件:拖拽排顺序,双击换画面** —— 顺序以前只能靠下面那排 ↑ / ↓
|
|
92
|
-
- **顺序和在屏的是哪张,从此互不干涉(这一条是修复)** ——
|
|
93
|
-
- **在屏那张不再有边框,只留圆点** —— `.is-sel`
|
|
94
|
-
- **一次上传的多张图,每一张都会各自取色** ——
|
|
95
|
-
- **卡片文案精简,「编辑位置」换了位置** ——
|
|
96
|
-
- **门禁** —— `check:repaint`
|
|
81
|
+
- **胶片条自己就是控件:拖拽排顺序,双击换画面** —— 顺序以前只能靠下面那排 ↑ / ↓ 和一个「设为第一张」按钮改,而五个缩略图本来就把顺序摆在那里。落点画成一根 2px 竖条,画在目标格子**内部**,因为一块占位的竖条会把指针正在测量的那些格子推走。而「哪张在屏上」是胶片条的**另一个**手势,且**不写任何配置**:在屏哪张是运行时状态而不是设置,所以下次启动照旧从规则的第一张开始。
|
|
82
|
+
- **顺序和在屏的是哪张,从此互不干涉(这一条是修复)** —— 旧的两个动作都以「把图片下标挪到刚被移动的那张图上」结尾,于是整理列表会把壁纸一起换掉。新的 `moveRuleImageTo(id, slot, to)` 取代了它们两个:摘出之前先记下**正在画的那个槽位**,插回去之后把下标放回它身上。
|
|
83
|
+
- **在屏那张不再有边框,只留圆点** —— `.is-sel` 已经给「正在编辑的那张」画了圈,再给「正在显示的那张」画一个,就成了一排几乎一样的缩略图里同时有两个「选中」。现在在屏 = 右上角那个圆点,仅此而已。
|
|
84
|
+
- **一次上传的多张图,每一张都会各自取色** —— 主题色属于**图片**,而取色是**按下标**寻址的:`addRuleImages` 先把整批追加完,然后只对最后一张取色,于是它之前的那些图没有自己的颜色、留在系统主题上。现在按**这一批自己刚追加的那些槽位**寻址。
|
|
85
|
+
- **卡片文案精简,「编辑位置」换了位置** —— 「规则列表」标题和两句解释都删了(面板标题与第一张卡上的 `兜底` 徽章已经说明了),标签去掉多余的名词(`第 1 / 5`、`添加` / `替换` / `移除`),`编辑位置` 移到布局模式那一行的末尾 —— 它打开的东西编辑的正是那一行五个模式在说的事。
|
|
86
|
+
- **门禁** —— `check:repaint` 新增一节钉住批量取色,`moveRuleImageTo` 进入「先采样 winner、再以 `repaintIfMoved` 收尾」的清单,两个被删掉的动作则从中移出。`check:ui` 覆盖新文案与新类。
|
|
97
87
|
|
|
98
88
|
## v0.7.1
|
|
99
89
|
|
|
100
|
-
- **主题色下放到图片** ——
|
|
101
|
-
- **规则自己的 `color` 只剩一个含义:一张图都没有时它画什么** ——
|
|
102
|
-
- **升级不丢主题色,而区分只靠一个键** —— 这个版本之前写下的图片条目**根本没有** `color`
|
|
103
|
-
- **轮换每一步都重发界面调色板,否则这个功能一出生就带着那个 bug** —— 换图原本只重画壁纸,于是「逐图主题色」只存在于配置和面板里,界面配色要等**别的**事情顺手重跑一次 apply
|
|
104
|
-
- **节日配色同样逐图** —— 节日的固定配色同时写在节日条目**和它的图片**上,`normalizeHolidayRule`
|
|
105
|
-
- **配置格式升到 4,旧宿主依旧吃不掉配置** —— `images[].color` 对 schema 3 的 `normalizeImage`
|
|
106
|
-
- **没有图片的规则只剩一个上传入口** —— 上方那块大预览**本身就是按钮**了(真正的 `<button
|
|
107
|
-
- **门禁** —— `check:node` 通过真实 RPC
|
|
90
|
+
- **主题色下放到图片** —— 一条规则是一组图片的轮换,而这些图往往是为不同心情收的、不该共用一个强调色,所以每张图现在带自己的 `color: [h, s, l] | null`,整个调色区作用于**胶片条里选中的那张图**。控件上方多了一行写明目标(「作用于选中的图片:2 / 3」),胶片条标出哪些图已经各自有颜色,因为一个会悄悄换目标的区块,正是「我改了颜色却没反应」的开端。没有新控件、也没有布局改动。
|
|
91
|
+
- **规则自己的 `color` 只剩一个含义:一张图都没有时它画什么** —— 它刻意**不是**该规则图片的默认值。没有自己颜色的图**跟随系统主题**,而不是去继承规则色,正是这一点才让「绿的、红的、跟随系统主题」这样一组轮换可以表达。所以清空某张图的颜色只影响那一张;规则自己的颜色留着,等「只剩它能画」的那个状态。
|
|
92
|
+
- **升级不丢主题色,而区分只靠一个键** —— 这个版本之前写下的图片条目**根本没有** `color` 键,这就是全部判据:缺键 = 「这张图从来没有自己的颜色」,于是规则色被抬升到它身上(只做一次,且在共享 sanitizer 里做)。显式 `null` = 「主动清空过」,任何时候都不会被重新继承覆盖 —— 这也是为什么每次写入都会带上这个键、哪怕是 null。
|
|
93
|
+
- **轮换每一步都重发界面调色板,否则这个功能一出生就带着那个 bug** —— 换图原本只重画壁纸,于是「逐图主题色」只存在于配置和面板里,界面配色要等**别的**事情顺手重跑一次 apply 才跟上。现在调色板的施加收成一个函数(`applyPalette`),模型切换和轮换的每一步都走它。只要 `paintImage` 或 `applyActive` 不再经过它,`pnpm check:repaint` 就会报错。
|
|
94
|
+
- **节日配色同样逐图** —— 节日的固定配色同时写在节日条目**和它的图片**上,`normalizeHolidayRule` 每次读取都用定义强制覆盖两处。所以「节日多图轮换、每张带自己的配色」已经只差 `HOLIDAYS` 与它的素材,而不需要在渲染层再开一条代码路径。
|
|
95
|
+
- **配置格式升到 4,旧宿主依旧吃不掉配置** —— `images[].color` 对 schema 3 的 `normalizeImage` 是未知字段,而它会**按自己认识的键重建**每个图片条目:颜色会一直在内存里活到下一次重新加载,然后悄无声息地消失。`SCHEMA_VERSION = 4` 在每次 `read` 时公布,报出更低版本的宿主会进入扣住写入的分支。主题文件升到格式 5。
|
|
96
|
+
- **没有图片的规则只剩一个上传入口** —— 上方那块大预览**本身就是按钮**了(真正的 `<button>`,可聚焦、可键盘触发;点它上传,也可以把文件拖上去),而胶片条在一张图都没有时**完全不渲染**,因为胶片条是一组图片的列表。拖放处理跟着一起上移而不是消失;有图片时预览依旧刻意保持惰性。
|
|
97
|
+
- **门禁** —— `check:node` 通过真实 RPC 处理器把逐图主题色这套形状端到端跑了一遍,`check:repaint` 多了一节「轮换步骤必须重发调色板」,`check:ui` 覆盖新文案与两个新类。
|
|
108
98
|
|
|
109
99
|
## v0.7.0
|
|
110
100
|
|
|
111
101
|
- **每条规则多图轮换 —— 默认关闭** —— 规则现在持有一组有序图片(`images: [{ slot, bgState }]`),可以按自己的节奏循环:10 秒 / 30 秒 / 1 分钟 / 5 分钟 / 30 分钟 / 1 小时,或 5 秒 – 24 小时之间的任意秒数;顺序可选**按顺序**或**随机**。默认是关的:轮换真的要花流量、内存和电,一个偷偷让壁纸动起来的默认值,等于替用户做了决定。
|
|
112
|
-
- **第二种触发完全不需要定时器** ——
|
|
113
|
-
- **随机绝不会抽到当前正在显示的那张** —— 挑选在**除当前这张之外**的所有下标上等概率进行,因为一次「图没变」的 tick 与一次「压根没触发」的 tick 完全无法区分 —— 而这正是这个功能唯一可能悄无声息失败的方式。`pnpm check:rotation` 对 2、3、7
|
|
114
|
-
- **全插件只有一个定时器,始终对准生效规则,按签名重排** ——
|
|
115
|
-
- **换的只有画面,规则本身不动** ——
|
|
102
|
+
- **第二种触发完全不需要定时器** —— 「切换模型时也换一张」:每次切换模型落到这条规则上就前进一张。不排期、不唤醒,只在用户做事的时候换图。
|
|
103
|
+
- **随机绝不会抽到当前正在显示的那张** —— 挑选在**除当前这张之外**的所有下标上等概率进行,因为一次「图没变」的 tick 与一次「压根没触发」的 tick 完全无法区分 —— 而这正是这个功能唯一可能悄无声息失败的方式。`pnpm check:rotation` 对 2、3、7 张图的列表把整个随机取值范围**穷举**了一遍,而不是抽一次样本。
|
|
104
|
+
- **全插件只有一个定时器,始终对准生效规则,按签名重排** —— 每条规则一个定时器会让根本没在画的规则白白唤醒,而屏幕上同时只可能有一条规则的图。它只在排期真正依赖的那些输入组成的签名变化时重排:规则 id、开关、间隔、顺序、图片数量、标签页可见性 —— 所以拖动滑块导致每秒重跑几十次 apply 也不会把停留计时反复清零。标签页隐藏时轮换跟着画面一起停下,回到前台时按全新间隔重新计时。
|
|
105
|
+
- **换的只有画面,规则本身不动** —— 主题色、布局模式、背景透明度与模糊度都留在规则上,过渡用的就是切换模型时那套双层交叉淡入。`fadeMs: 0` 是一个真实取值,不会被当成「没设置」。
|
|
116
106
|
- **取景移到图片上,这才是它该在的地方** —— 构图属于某一张图:两张宽高比不同的壁纸共享规则的模式、颜色、透明度与模糊度,但为第一张算出来的那套适应取景,用在第二张上就是错的。每张图各自带一份 `bgState`,背景编辑器编辑的是胶片条里选中的那一张。
|
|
117
|
-
- **单图缩略图变成胶片条** —— 可一次加多张(**多选文件**、**拖放**,或**一行一个网址**批量粘贴,逐个下载以免 N
|
|
118
|
-
- **规则可以一张图都没有,而这是一个必须成立的状态** ——
|
|
119
|
-
- **一张图都没有的规则,靠主题色继续生效** ——
|
|
120
|
-
- **凡是可能改变「谁赢」的编辑,现在都立刻生效;只有不可能改变的才允许跳过重画** —— `color`、`enabled`、`match`
|
|
121
|
-
- **清空之后再上传** ——
|
|
122
|
-
- **只加载用得到的图** ——
|
|
123
|
-
- **旧宿主进程再也不可能吃掉一份配置 —— 判定改成版本比较,格式版本因此升到 3** —— 浏览器半边与 node 半边是分开加载的,所以「更新包之后只刷新一次页面」会把**新的**客户端 bundle 与仍在运行**上一个** node
|
|
124
|
-
- **老配置照常读,老导出照常导入** —— `normalizeRule` 同时接受两种形状:规则里那对单图字段(`slot` / `bgState`)在读取时被提升成 `images: [{ slot, bgState }]`,同一条规则里重复的槽位被去掉,不可用的槽位被去掉。主题导出升到**格式版本 4
|
|
107
|
+
- **单图缩略图变成胶片条** —— 可一次加多张(**多选文件**、**拖放**,或**一行一个网址**批量粘贴,逐个下载以免 N 个请求互相穿插、连进度都没法显示)、点选要编辑的那张、排序、设为**第一张**、**原地替换这张**(替换会保住它在轮换里的位置,所以它与「添加」分开命名)、或删除。
|
|
108
|
+
- **规则可以一张图都没有,而这是一个必须成立的状态** —— 第一版拒绝删除最后一张,转而「清空它的字节」,结果留下的正是条目本身:胶片条第 1 位一块永远删不掉的空白图。现在删除最后一张就是把列表清空;新建的规则也从空列表开始;手改导致「每一项都不可用」的列表同样落到这个状态,而不是被硬塞回一个坏槽位。
|
|
109
|
+
- **一张图都没有的规则,靠主题色继续生效** —— 第一版把空列表当成了「这条规则失效」:「可用」只看有没有图,于是一条图片删光、主题色还在的规则**不再参与匹配**,而它原本匹配的模型还会被悄悄交给**下一条**规则。现在判定标准是**有图,或者有自己的主题色**(`ruleCanPaint`):这样的规则照旧匹配、照旧当兜底,只是不铺壁纸、只给界面配色。面板上的提示也按三种真实状态分开说。
|
|
110
|
+
- **凡是可能改变「谁赢」的编辑,现在都立刻生效;只有不可能改变的才允许跳过重画** —— `color`、`enabled`、`match` 都参与「哪条规则赢」的判定,但每条写入路径各自只问「这条规则是不是正在画的那条?」,于是只有对**已经**在生效的那条规则的编辑会重画 —— 而「本来没在生效」的编辑恰恰就是**制造**赢家的那些。现在每条路径都会在改动**之前**取一次赢家、改动之后再做比较(`repaintIfMoved`),`pnpm check:repaint` 在入口文件里那九条写入路径中的任何一条不再询问它时会失败。
|
|
111
|
+
- **清空之后再上传** —— 你加进去的那张就是你正在看的那张:卡片会把编辑焦点移到新加入的第一张,胶片条、大预览与位置读数一起跟上,而不是把面板留在之前选中的东西上。
|
|
112
|
+
- **只加载用得到的图** —— 启动时只灌每条规则的**第一张**(与多图出现之前每条规则灌一张完全一致),外加今天生效的节日图与当前模型正在画的那张;其余的在展开卡片时、或轮换即将用到它时再取。若在启动时灌满每条规则的每张图,「五条规则各四张」就意味着首帧之前先把二十张全尺寸 data URL 从本插件自己的 RPC 通道推一遍。
|
|
113
|
+
- **旧宿主进程再也不可能吃掉一份配置 —— 判定改成版本比较,格式版本因此升到 3** —— 浏览器半边与 node 半边是分开加载的,所以「更新包之后只刷新一次页面」会把**新的**客户端 bundle 与仍在运行**上一个** node 半边的宿主进程配在一起,而那个旧 sanitizer 完全不认识 `images`,于是会在下一次拖动滑块时悄无声息地丢掉每一条规则。因此 node 半边会公布自己写入的配置格式,而发现答案是旧版的客户端会**扣住所有配置写入**、在控制台警告一次,并在面板里说明「重启 DSH」。悄悄不保存的修改,比明说要等重启的修改更糟;而悄悄删掉规则的修改,比两者都糟。这个版本号现在表示的是「**空图片列表合法**」(`SCHEMA_VERSION = 3`),而不只是「规则里有 `images` 字段」,所以任何报出更低版本的宿主一律进入扣住写入的状态。
|
|
114
|
+
- **老配置照常读,老导出照常导入** —— `normalizeRule` 同时接受两种形状:规则里那对单图字段(`slot` / `bgState`)在读取时被提升成 `images: [{ slot, bgState }]`,同一条规则里重复的槽位被去掉,不可用的槽位被去掉。主题导出升到**格式版本 4**,导出与还原的是每条规则的**全部**图片;版本 3 的文件仍可导入。
|
|
125
115
|
- **各图槽位互不干扰,删除规则只回收它自己那份** —— 一条三张图的规则占三个 `modelbg-<slot>` 文件;`nextSlot` 扫描配置里的**每一个**槽位(用户规则**与**节日条目都算),所以新加的一张图绝不会撞上已有的槽位;删除规则时,只有当某个槽位不再被任何地方引用时才回收。
|
|
126
|
-
- **node 半边连嵌套字段的漂移也一并报告,迁移直接写新形状** —— `warnUnknownConfigKeys` 现在会往深一层比较 `rules[].rotate` 与 `rules[].images[]` —— 一个只有客户端 bundle 知道的字段正是在那里无声消失的;同时 `slot` / `bgState` 这两个旧字段名被明确豁免,因为 sanitizer 是**故意**要提升它们的。0.3
|
|
116
|
+
- **node 半边连嵌套字段的漂移也一并报告,迁移直接写新形状** —— `warnUnknownConfigKeys` 现在会往深一层比较 `rules[].rotate` 与 `rules[].images[]` —— 一个只有客户端 bundle 知道的字段正是在那里无声消失的;同时 `slot` / `bgState` 这两个旧字段名被明确豁免,因为 sanitizer 是**故意**要提升它们的。0.3 之前配置的迁移也直接写出图片列表。
|
|
127
117
|
|
|
128
118
|
## v0.6.0
|
|
129
119
|
|