wallpaper-engine-dsh 1.0.8 → 2.0.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/lib/client.js +61 -11
- package/package.json +12 -7
package/lib/client.js
CHANGED
|
@@ -10,6 +10,11 @@ window.__ModuleLoader__.load({
|
|
|
10
10
|
const SETTINGS_KEY = "wallpaper-engine-dsh:selection";
|
|
11
11
|
const INVENTORY_URL = "/we-background/inventory";
|
|
12
12
|
const ACTIVE_ATTR = "data-webg-wallpaper";
|
|
13
|
+
// Plugin-owned dark-theme signal for CSS. The shell's old dark-mode body
|
|
14
|
+
// attribute is gone in DSH >= 0.2.1-rc.5; the client now derives dark from
|
|
15
|
+
// the shell's theme service and mirrors it here, so the stylesheet never
|
|
16
|
+
// keys off host DOM internals.
|
|
17
|
+
const DARK_ATTR = "data-webg-dark";
|
|
13
18
|
const LAYER_ID = "wallpaper-engine-dsh-layer";
|
|
14
19
|
const SCRIM_ID = "wallpaper-engine-dsh-scrim";
|
|
15
20
|
const STYLE_TAG_ID = "wallpaper-engine-dsh/styles";
|
|
@@ -1093,6 +1098,9 @@ window.__ModuleLoader__.load({
|
|
|
1093
1098
|
// tick would rewrite all CSS variables AND force a synchronous layout for
|
|
1094
1099
|
// nothing. clearEffects() resets it so the next apply always writes.
|
|
1095
1100
|
let lastEffectKey = null;
|
|
1101
|
+
// Resolved dark-theme state, driven by the shell theme service (or the OS
|
|
1102
|
+
// prefers-color-scheme fallback). Mirrored onto body[DARK_ATTR] for CSS.
|
|
1103
|
+
let themeDark = false;
|
|
1096
1104
|
|
|
1097
1105
|
/** Average Rec.601 luminance (0..1) of a drawable media frame, or null. */
|
|
1098
1106
|
function luminanceOf(media) {
|
|
@@ -1163,7 +1171,16 @@ window.__ModuleLoader__.load({
|
|
|
1163
1171
|
// The veil OPPOSES the text colour: dark theme (light text) darkens bright
|
|
1164
1172
|
// wallpapers, light theme (dark text) brightens dark ones — either way the
|
|
1165
1173
|
// text side wins. This is what makes ANY wallpaper survivable.
|
|
1166
|
-
const dark =
|
|
1174
|
+
const dark = themeDark;
|
|
1175
|
+
if (typeof document !== "undefined" && document.body) {
|
|
1176
|
+
if (dark) {
|
|
1177
|
+
if (!(document.body.hasAttribute && document.body.hasAttribute(DARK_ATTR))) {
|
|
1178
|
+
document.body.setAttribute(DARK_ATTR, "");
|
|
1179
|
+
}
|
|
1180
|
+
} else if (document.body.hasAttribute && document.body.hasAttribute(DARK_ATTR)) {
|
|
1181
|
+
document.body.removeAttribute(DARK_ATTR);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1167
1184
|
const roundedLum = sampledLuminance !== null ? Math.round(sampledLuminance * 100) / 100 : null;
|
|
1168
1185
|
const key = [
|
|
1169
1186
|
dark, selection.scrim, selection.border, selection.blur, selection.wallpaperBlur,
|
|
@@ -1911,7 +1928,7 @@ window.__ModuleLoader__.load({
|
|
|
1911
1928
|
|
|
1912
1929
|
/* Light-scheme text ramp: grays were tuned against a near-white page and
|
|
1913
1930
|
lose contrast over busy wallpapers — push them darker while active. */
|
|
1914
|
-
body[${ACTIVE_ATTR}]:not([
|
|
1931
|
+
body[${ACTIVE_ATTR}]:not([${DARK_ATTR}]) {
|
|
1915
1932
|
--dsw-alias-label-primary: rgb(0, 0, 0);
|
|
1916
1933
|
--dsw-alias-label-primary-dimmed: rgb(10, 10, 12);
|
|
1917
1934
|
--dsw-alias-label-secondary: rgb(40, 42, 46);
|
|
@@ -1929,7 +1946,7 @@ window.__ModuleLoader__.load({
|
|
|
1929
1946
|
--dsw-specific-input-major: rgba(255, 255, 255, 0.15);
|
|
1930
1947
|
--dsw-specific-bubble: rgba(255, 255, 255, 0.12);
|
|
1931
1948
|
}
|
|
1932
|
-
body[
|
|
1949
|
+
body[${DARK_ATTR}][${ACTIVE_ATTR}] {
|
|
1933
1950
|
--dsw-specific-input-major: rgba(255, 255, 255, 0.06);
|
|
1934
1951
|
--dsw-specific-bubble: rgba(255, 255, 255, 0.05);
|
|
1935
1952
|
}
|
|
@@ -2170,7 +2187,10 @@ window.__ModuleLoader__.load({
|
|
|
2170
2187
|
`;
|
|
2171
2188
|
|
|
2172
2189
|
// ── Plugin exports ──────────────────────────────────────────────────────────
|
|
2173
|
-
|
|
2190
|
+
// The client runner (dsh-cordis-client-runner) rejects ctx.get() of any
|
|
2191
|
+
// service this plugin does not declare. slots registers the settings row,
|
|
2192
|
+
// locale drives the bilingual UI, theme drives the veil/scheme reactions.
|
|
2193
|
+
const inject = ["slots", "locale", "theme"];
|
|
2174
2194
|
|
|
2175
2195
|
function apply(ctx) {
|
|
2176
2196
|
// A plugin UPDATE re-applies this module WITHOUT re-evaluating it: the old
|
|
@@ -2198,6 +2218,42 @@ window.__ModuleLoader__.load({
|
|
|
2198
2218
|
} catch { /* event bus unavailable → static language */ }
|
|
2199
2219
|
}
|
|
2200
2220
|
|
|
2221
|
+
// 0b. Theme: follow the shell's theme service (snapshot.active.colorScheme
|
|
2222
|
+
// is "light"|"dark"; "theme/change" emits the new snapshot). Without
|
|
2223
|
+
// the service, fall back to the OS prefers-color-scheme media query.
|
|
2224
|
+
// A flip re-runs applyEffects() so the veil colour (black ↔ white) and
|
|
2225
|
+
// the DARK_ATTR mirror follow immediately.
|
|
2226
|
+
const themeSvc = typeof ctx.get === "function" ? ctx.get("theme") : undefined;
|
|
2227
|
+
if (themeSvc && typeof themeSvc.getTheme === "function") {
|
|
2228
|
+
try {
|
|
2229
|
+
const snap = themeSvc.getTheme();
|
|
2230
|
+
themeDark = Boolean(snap && snap.active && snap.active.colorScheme === "dark");
|
|
2231
|
+
} catch { /* keep previous state */ }
|
|
2232
|
+
if (typeof ctx.on === "function") {
|
|
2233
|
+
try {
|
|
2234
|
+
ctx.on("theme/change", (snap) => {
|
|
2235
|
+
const next = Boolean(snap && snap.active && snap.active.colorScheme === "dark");
|
|
2236
|
+
if (next !== themeDark) { themeDark = next; applyEffects(); }
|
|
2237
|
+
});
|
|
2238
|
+
} catch { /* event bus unavailable → static theme */ }
|
|
2239
|
+
}
|
|
2240
|
+
} else if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
|
|
2241
|
+
try {
|
|
2242
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
2243
|
+
themeDark = Boolean(mq && mq.matches);
|
|
2244
|
+
if (typeof mq.addEventListener === "function") {
|
|
2245
|
+
const onScheme = (e) => {
|
|
2246
|
+
const next = Boolean(e && e.matches);
|
|
2247
|
+
if (next !== themeDark) { themeDark = next; applyEffects(); }
|
|
2248
|
+
};
|
|
2249
|
+
mq.addEventListener("change", onScheme);
|
|
2250
|
+
if (typeof ctx.effect === "function") {
|
|
2251
|
+
ctx.effect(() => () => mq.removeEventListener("change", onScheme));
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
} catch { /* no matchMedia → light default */ }
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2201
2257
|
// 1. Styles: owned by the fiber — injected on apply, REMOVED on dispose.
|
|
2202
2258
|
if (ctx.effect && typeof document !== "undefined") {
|
|
2203
2259
|
ctx.effect(() => {
|
|
@@ -2230,12 +2286,6 @@ window.__ModuleLoader__.load({
|
|
|
2230
2286
|
applyEffects();
|
|
2231
2287
|
}, 2500);
|
|
2232
2288
|
}
|
|
2233
|
-
// A theme switch flips the veil colour immediately (black ↔ white).
|
|
2234
|
-
let observer = null;
|
|
2235
|
-
if (typeof MutationObserver === "function") {
|
|
2236
|
-
observer = new MutationObserver(() => applyEffects());
|
|
2237
|
-
observer.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] });
|
|
2238
|
-
}
|
|
2239
2289
|
return () => {
|
|
2240
2290
|
// Stop any in-flight inventory fetch from committing state (and
|
|
2241
2291
|
// re-arming the rotation timer) after teardown began.
|
|
@@ -2246,7 +2296,6 @@ window.__ModuleLoader__.load({
|
|
|
2246
2296
|
// removes the bar and its listeners) before tearing layers down.
|
|
2247
2297
|
exitAdjust();
|
|
2248
2298
|
if (samplerId !== null) window.clearInterval(samplerId);
|
|
2249
|
-
if (observer) observer.disconnect();
|
|
2250
2299
|
sampledLuminance = null;
|
|
2251
2300
|
if (previewProbe) { previewProbe.remove(); previewProbe = null; }
|
|
2252
2301
|
clearRotationTimer();
|
|
@@ -2265,6 +2314,7 @@ window.__ModuleLoader__.load({
|
|
|
2265
2314
|
if (scrim) scrim.remove();
|
|
2266
2315
|
clearEffects();
|
|
2267
2316
|
document.body.removeAttribute(ACTIVE_ATTR);
|
|
2317
|
+
document.body.removeAttribute(DARK_ATTR);
|
|
2268
2318
|
};
|
|
2269
2319
|
});
|
|
2270
2320
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallpaper-engine-dsh",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Wallpaper Engine library as the DSH web GUI background — video/web/still wallpapers, rotation lists, search, resource monitor, bilingual UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"client": {
|
|
55
55
|
"inject": [
|
|
56
|
-
"@deepseek-ai/dsh-client-
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-settings-general"
|
|
57
57
|
],
|
|
58
58
|
"platform": "web",
|
|
59
59
|
"immediately": true
|
|
@@ -71,23 +71,28 @@
|
|
|
71
71
|
"release:major": "npm version major -m \"chore: release v%s\" && git push --follow-tags"
|
|
72
72
|
},
|
|
73
73
|
"engines": {
|
|
74
|
+
"dsh": ">=0.2.1-rc.5",
|
|
74
75
|
"node": ">=18.17"
|
|
75
76
|
},
|
|
76
77
|
"peerDependencies": {
|
|
77
78
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
78
|
-
"@deepseek-ai/dsh-client-
|
|
79
|
-
"@deepseek-ai/dsh-client-ui-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
79
|
+
"@deepseek-ai/dsh-client-locale": ">=0.2.1-rc.5",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-settings-general": ">=0.2.1-rc.5",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-theme": ">=0.2.1-rc.5",
|
|
82
|
+
"@deepseek-ai/dsh-host-webserver": ">=0.2.1-rc.5",
|
|
81
83
|
"react": "^18.2.0"
|
|
82
84
|
},
|
|
83
85
|
"peerDependenciesMeta": {
|
|
84
86
|
"@deepseek-ai/cordis": {
|
|
85
87
|
"optional": true
|
|
86
88
|
},
|
|
87
|
-
"@deepseek-ai/dsh-client-
|
|
89
|
+
"@deepseek-ai/dsh-client-locale": {
|
|
88
90
|
"optional": true
|
|
89
91
|
},
|
|
90
|
-
"@deepseek-ai/dsh-client-ui-
|
|
92
|
+
"@deepseek-ai/dsh-client-ui-settings-general": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@deepseek-ai/dsh-client-ui-theme": {
|
|
91
96
|
"optional": true
|
|
92
97
|
},
|
|
93
98
|
"@deepseek-ai/dsh-host-webserver": {
|