dsh-background-by-model 0.7.2 → 0.7.4
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 +180 -160
- package/CHANGELOG.zh.md +181 -159
- package/LICENSE +21 -21
- package/README.md +297 -283
- package/README.zh.md +297 -283
- package/cordis.patch.yml +8 -8
- package/lib/client.js +704 -49
- package/lib/client.js.map +1 -1
- package/lib/index.js +86 -8
- package/package.json +3 -2
package/lib/index.js
CHANGED
|
@@ -59,15 +59,12 @@ const ROTATE_ORDERS = ["order", "shuffle"];
|
|
|
59
59
|
const ROTATE_MIN_MS = 5e3;
|
|
60
60
|
/** Slowest allowed dwell time (24 h): one image per day is still "rotation". */
|
|
61
61
|
const ROTATE_MAX_MS = 864e5;
|
|
62
|
-
/** Longest allowed cross-fade; 0 is a hard cut. */
|
|
63
|
-
const ROTATE_FADE_MAX_MS = 3e3;
|
|
64
62
|
/** Everything off: the shipped default, and what a config predating this feature gets. */
|
|
65
63
|
const DEFAULT_ROTATION = {
|
|
66
64
|
enabled: false,
|
|
67
65
|
intervalMs: 6e4,
|
|
68
66
|
order: "order",
|
|
69
|
-
advanceOnSwitch: false
|
|
70
|
-
fadeMs: 320
|
|
67
|
+
advanceOnSwitch: false
|
|
71
68
|
};
|
|
72
69
|
/** A fresh rotation block (never hand out the shared default object). */
|
|
73
70
|
function defaultRotation() {
|
|
@@ -124,6 +121,28 @@ const DEFAULT_PART_BLURS = {
|
|
|
124
121
|
rightbar: 0,
|
|
125
122
|
input: 0
|
|
126
123
|
};
|
|
124
|
+
/** Longest allowed switch duration; 0 is a hard cut. */
|
|
125
|
+
const TRANSITION_MAX_MS = 3e3;
|
|
126
|
+
/** Every accepted `effect`, in UI order. */
|
|
127
|
+
const TRANSITION_EFFECTS = [
|
|
128
|
+
"fade",
|
|
129
|
+
"none",
|
|
130
|
+
"zoom",
|
|
131
|
+
"slide"
|
|
132
|
+
];
|
|
133
|
+
/** Every accepted `easing`, in UI order. */
|
|
134
|
+
const TRANSITION_EASINGS = [
|
|
135
|
+
"ease",
|
|
136
|
+
"linear",
|
|
137
|
+
"ease-out",
|
|
138
|
+
"ease-in-out"
|
|
139
|
+
];
|
|
140
|
+
/** The shipped default: the cross-fade this plugin already performed, at 320 ms. */
|
|
141
|
+
const DEFAULT_TRANSITION = {
|
|
142
|
+
effect: "fade",
|
|
143
|
+
easing: "ease",
|
|
144
|
+
durationMs: 320
|
|
145
|
+
};
|
|
127
146
|
/**
|
|
128
147
|
* `#RRGGBB` → the `[h, s, l]` triple every rule stores (`s` and `l` in 0..1), or
|
|
129
148
|
* null when the string is not a hex color.
|
|
@@ -220,8 +239,7 @@ function normalizeRotation(raw) {
|
|
|
220
239
|
enabled: r.enabled === true,
|
|
221
240
|
intervalMs: clamp(r.intervalMs, ROTATE_MIN_MS, ROTATE_MAX_MS, d.intervalMs),
|
|
222
241
|
order: ROTATE_ORDERS.includes(r.order) ? r.order : d.order,
|
|
223
|
-
advanceOnSwitch: r.advanceOnSwitch === true
|
|
224
|
-
fadeMs: clamp(r.fadeMs, 0, ROTATE_FADE_MAX_MS, d.fadeMs)
|
|
242
|
+
advanceOnSwitch: r.advanceOnSwitch === true
|
|
225
243
|
};
|
|
226
244
|
}
|
|
227
245
|
/** Own-property test for values that may be anything at all (a raw JSON entry). */
|
|
@@ -229,6 +247,54 @@ function hasOwn(o, key) {
|
|
|
229
247
|
return Object.prototype.hasOwnProperty.call(o, key);
|
|
230
248
|
}
|
|
231
249
|
/**
|
|
250
|
+
* The duration a config written before the switch effect carries on any of its
|
|
251
|
+
* rules, or `undefined` when it carries none worth adopting.
|
|
252
|
+
*
|
|
253
|
+
* `rotate.fadeMs` was the per-rule duration from 0.7.0 on, and it had NO control
|
|
254
|
+
* anywhere — it could only be hand-edited, which is why the global setting
|
|
255
|
+
* replaced it. This is the one-shot lift that keeps such a hand-tuned value from
|
|
256
|
+
* being silently dropped on upgrade: the first rule whose value differs from the
|
|
257
|
+
* 320 ms every build shipped is adopted as the global duration. Values that are
|
|
258
|
+
* all the default are ignored, so an ordinary config keeps the ordinary default,
|
|
259
|
+
* and rules that DISAGREE cannot be represented by one global number — the first
|
|
260
|
+
* deliberate value wins, and the others are gone with the field they lived on.
|
|
261
|
+
*/
|
|
262
|
+
function legacyFadeMs(rawRules) {
|
|
263
|
+
if (!Array.isArray(rawRules)) return void 0;
|
|
264
|
+
for (const entry of rawRules) {
|
|
265
|
+
const rotate = entry?.rotate;
|
|
266
|
+
if (rotate === null || typeof rotate !== "object") continue;
|
|
267
|
+
const value = rotate.fadeMs;
|
|
268
|
+
if (typeof value !== "number" || !isFinite(value)) continue;
|
|
269
|
+
if (value === DEFAULT_TRANSITION.durationMs) continue;
|
|
270
|
+
return clamp(value, 0, TRANSITION_MAX_MS, DEFAULT_TRANSITION.durationMs);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Coerce one persisted transition block; a config written before this setting
|
|
275
|
+
* existed has no `transition` key at all and gets the shipped default, which is
|
|
276
|
+
* the behaviour it already had.
|
|
277
|
+
*
|
|
278
|
+
* `legacyMs` is the per-rule `fadeMs` this shape replaced (see `legacyFadeMs`),
|
|
279
|
+
* adopted only when the incoming config has no `durationMs` of its own — so a
|
|
280
|
+
* deliberate hand-tuned blend survives the upgrade instead of being dropped with
|
|
281
|
+
* the field it used to live on.
|
|
282
|
+
*
|
|
283
|
+
* `durationMs` is clamped with `0` kept as a real value (a hard cut) rather than
|
|
284
|
+
* read as "absent": 0 is exactly how a hard cut is asked for without changing
|
|
285
|
+
* the effect.
|
|
286
|
+
*/
|
|
287
|
+
function normalizeTransition(raw, legacyMs) {
|
|
288
|
+
const t = raw ?? {};
|
|
289
|
+
const d = DEFAULT_TRANSITION;
|
|
290
|
+
const fallback = typeof legacyMs === "number" && isFinite(legacyMs) ? legacyMs : d.durationMs;
|
|
291
|
+
return {
|
|
292
|
+
effect: TRANSITION_EFFECTS.includes(t.effect) ? t.effect : d.effect,
|
|
293
|
+
easing: TRANSITION_EASINGS.includes(t.easing) ? t.easing : d.easing,
|
|
294
|
+
durationMs: clamp(t.durationMs, 0, TRANSITION_MAX_MS, fallback)
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
232
298
|
* Coerce one persisted image entry, or null when it lacks a usable slot.
|
|
233
299
|
*
|
|
234
300
|
* `inherit` is the RULE's own color, and it is applied only to an entry that has
|
|
@@ -365,6 +431,7 @@ function normalizeConfig(raw) {
|
|
|
365
431
|
rules,
|
|
366
432
|
opacities,
|
|
367
433
|
blurs,
|
|
434
|
+
transition: normalizeTransition(r.transition, legacyFadeMs(r.rules)),
|
|
368
435
|
settingsOpacity: clamp01(r.settingsOpacity, 1),
|
|
369
436
|
chatTextOpacity: clamp01(r.chatTextOpacity, 0),
|
|
370
437
|
trajectoryOpacity: clamp01(r.trajectoryOpacity, 1),
|
|
@@ -498,6 +565,7 @@ const LEGACY_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
498
565
|
"bgState"
|
|
499
566
|
]);
|
|
500
567
|
const LEGACY_RULE_KEYS = /* @__PURE__ */ new Set(["slot", "bgState"]);
|
|
568
|
+
const LEGACY_NESTED_KEYS = /* @__PURE__ */ new Set(["rules[].rotate.fadeMs"]);
|
|
501
569
|
const warnedConfigKeys = /* @__PURE__ */ new Set();
|
|
502
570
|
function warnUnknownConfigKeys(raw, normalized) {
|
|
503
571
|
if (raw === null || typeof raw !== "object") return;
|
|
@@ -516,6 +584,16 @@ function warnUnknownConfigKeys(raw, normalized) {
|
|
|
516
584
|
const keys = new Set(Object.keys(have));
|
|
517
585
|
for (const key of Object.keys(got)) if (!keys.has(key)) warned(`${group}.${key}`);
|
|
518
586
|
}
|
|
587
|
+
const shapes = [[
|
|
588
|
+
"transition",
|
|
589
|
+
r.transition,
|
|
590
|
+
normalized.transition
|
|
591
|
+
]];
|
|
592
|
+
for (const [label, got, known] of shapes) {
|
|
593
|
+
if (got === null || typeof got !== "object") continue;
|
|
594
|
+
const keys = new Set(Object.keys(known));
|
|
595
|
+
for (const key of Object.keys(got)) if (!keys.has(key)) warned(`${label}.${key}`);
|
|
596
|
+
}
|
|
519
597
|
const sent = Array.isArray(r.rules) ? r.rules[0] : void 0;
|
|
520
598
|
const have = normalized.rules[0];
|
|
521
599
|
if (sent !== null && typeof sent === "object" && have !== void 0) {
|
|
@@ -534,7 +612,7 @@ function warnUnknownConfigKeys(raw, normalized) {
|
|
|
534
612
|
for (const [label, got, known] of nested) {
|
|
535
613
|
if (got === null || typeof got !== "object" || known === null || known === void 0) continue;
|
|
536
614
|
const knownKeys = new Set(Object.keys(known));
|
|
537
|
-
for (const key of Object.keys(got)) if (!knownKeys.has(key)) warned(`${label}.${key}`);
|
|
615
|
+
for (const key of Object.keys(got)) if (!knownKeys.has(key) && !LEGACY_NESTED_KEYS.has(`${label}.${key}`)) warned(`${label}.${key}`);
|
|
538
616
|
}
|
|
539
617
|
}
|
|
540
618
|
}
|
|
@@ -740,7 +818,7 @@ async function handleRpcMethod(ctx, endpoint, payload) {
|
|
|
740
818
|
value: {
|
|
741
819
|
config: await readConfig(),
|
|
742
820
|
slots: await listSlots(),
|
|
743
|
-
schema:
|
|
821
|
+
schema: 5
|
|
744
822
|
}
|
|
745
823
|
};
|
|
746
824
|
case "writeConfig": return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-background-by-model",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Appearance plugin for DeepSeek Harness: an ordered list of model rules, each carrying its own wallpapers — every image with its own framing and theme color — plus layout mode, opacity and blur; the background follows the model you switch to, and a rule can rotate through several images on its own rhythm.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -58,10 +58,11 @@
|
|
|
58
58
|
"typecheck": "tsc -p tsconfig.json",
|
|
59
59
|
"check:holiday": "node scripts/holiday-check.ts",
|
|
60
60
|
"check:rotation": "node scripts/rotation-check.ts",
|
|
61
|
+
"check:transition": "node scripts/transition-check.ts",
|
|
61
62
|
"check:repaint": "node scripts/repaint-check.ts",
|
|
62
63
|
"check:ui": "node scripts/ui-strings-check.ts",
|
|
63
64
|
"check:node": "node scripts/node-half-check.mjs",
|
|
64
|
-
"test": "tsdown && tsc -p tsconfig.json && node scripts/holiday-check.ts && node scripts/rotation-check.ts && node scripts/repaint-check.ts && node scripts/ui-strings-check.ts && node scripts/node-half-check.mjs"
|
|
65
|
+
"test": "tsdown && tsc -p tsconfig.json && node scripts/holiday-check.ts && node scripts/rotation-check.ts && node scripts/transition-check.ts && node scripts/repaint-check.ts && node scripts/ui-strings-check.ts && node scripts/node-half-check.mjs"
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|
|
67
68
|
"@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6",
|