wallpaper-engine-dsh 1.0.7 → 1.0.8
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/README.md +1 -0
- package/README.zh.md +1 -0
- package/lib/client.js +37 -13
- package/lib/core.js +7 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ Media serving is defensive by design: tokens are unguessable 72-bit values, stab
|
|
|
64
64
|
|
|
65
65
|
- Scene and application wallpapers are not listed: they are Wallpaper Engine's private `.pkg` scene packages, and their live animation can only be rendered by Wallpaper Engine itself on the desktop.
|
|
66
66
|
- Web wallpapers run isolated from the page's storage, so ones that persist state across loads won't keep it.
|
|
67
|
+
- Web wallpapers with sound may stay silent until you interact with the page — browsers gate audio in sandboxed documents on a user gesture, and wallpapers that rely on Wallpaper Engine's system-audio feed (visualizers) have no signal to draw from.
|
|
67
68
|
- The glass effect reads DSH design tokens; if a future shell redesign renames them, frosting degrades to plain transparency.
|
|
68
69
|
|
|
69
70
|
## Development
|
package/README.zh.md
CHANGED
|
@@ -64,6 +64,7 @@ bundle 分为两半:
|
|
|
64
64
|
|
|
65
65
|
- 场景与应用壁纸不出现在列表中:它们是 Wallpaper Engine 私有的 `.pkg` 场景包,动态渲染只能由桌面端的 Wallpaper Engine 完成。
|
|
66
66
|
- 网页壁纸与页面存储隔离,需要跨加载保存状态的壁纸无法保留状态。
|
|
67
|
+
- 带声音的网页壁纸可能在你与页面交互前保持静默——浏览器对沙箱文档的音频有自动播放限制;依赖 Wallpaper Engine 系统音频输入的壁纸(如音频可视化)在浏览器中没有信号可画。
|
|
67
68
|
- 玻璃效果读 DSH 设计令牌;若未来外壳重构重命名令牌,磨砂会退化为普通半透明。
|
|
68
69
|
|
|
69
70
|
## 开发
|
package/lib/client.js
CHANGED
|
@@ -688,6 +688,7 @@ window.__ModuleLoader__.load({
|
|
|
688
688
|
media = document.createElement("iframe");
|
|
689
689
|
media.src = sel.url;
|
|
690
690
|
media.setAttribute("sandbox", "allow-scripts");
|
|
691
|
+
media.setAttribute("allow", "autoplay");
|
|
691
692
|
media.setAttribute("referrerpolicy", "no-referrer");
|
|
692
693
|
media.setAttribute("frameborder", "0");
|
|
693
694
|
media.setAttribute("scrolling", "no");
|
|
@@ -1019,7 +1020,13 @@ window.__ModuleLoader__.load({
|
|
|
1019
1020
|
if (existing) {
|
|
1020
1021
|
existing.classList.add("webg-layer--leave");
|
|
1021
1022
|
const stale = existing;
|
|
1022
|
-
schedule(() =>
|
|
1023
|
+
schedule(() => {
|
|
1024
|
+
const v = stale.querySelector("video");
|
|
1025
|
+
if (v) { v.pause(); v.removeAttribute("src"); if (typeof v.load === "function") v.load(); }
|
|
1026
|
+
const f = stale.querySelector("iframe");
|
|
1027
|
+
if (f) { f.src = "about:blank"; }
|
|
1028
|
+
stale.remove();
|
|
1029
|
+
}, LEAVE_MS);
|
|
1023
1030
|
}
|
|
1024
1031
|
}
|
|
1025
1032
|
const node = document.getElementById(LAYER_ID);
|
|
@@ -1035,11 +1042,18 @@ window.__ModuleLoader__.load({
|
|
|
1035
1042
|
existing.classList.add("webg-layer--leave");
|
|
1036
1043
|
const stale = existing;
|
|
1037
1044
|
schedule(() => {
|
|
1045
|
+
const v = stale.querySelector("video");
|
|
1046
|
+
if (v) { v.pause(); v.removeAttribute("src"); if (typeof v.load === "function") v.load(); }
|
|
1047
|
+
const f = stale.querySelector("iframe");
|
|
1048
|
+
if (f) { f.src = "about:blank"; }
|
|
1038
1049
|
stale.remove();
|
|
1039
1050
|
if (!document.getElementById(LAYER_ID)) {
|
|
1040
1051
|
const s = document.getElementById(SCRIM_ID);
|
|
1041
1052
|
if (s) s.remove();
|
|
1042
1053
|
document.body.removeAttribute(ACTIVE_ATTR);
|
|
1054
|
+
if (previewProbe) { previewProbe.remove(); previewProbe = null; }
|
|
1055
|
+
sampledLuminance = null;
|
|
1056
|
+
clearEffects();
|
|
1043
1057
|
}
|
|
1044
1058
|
}, LEAVE_MS);
|
|
1045
1059
|
}
|
|
@@ -1060,6 +1074,9 @@ window.__ModuleLoader__.load({
|
|
|
1060
1074
|
if (selection.type === "web") {
|
|
1061
1075
|
const w = selection.inventory.wallpapers.find((x) => x.id === selection.id);
|
|
1062
1076
|
if (w && w.preview) probePreviewLuminance(w.preview);
|
|
1077
|
+
} else if (previewProbe) {
|
|
1078
|
+
previewProbe.remove();
|
|
1079
|
+
previewProbe = null;
|
|
1063
1080
|
}
|
|
1064
1081
|
}
|
|
1065
1082
|
}
|
|
@@ -1147,9 +1164,10 @@ window.__ModuleLoader__.load({
|
|
|
1147
1164
|
// wallpapers, light theme (dark text) brightens dark ones — either way the
|
|
1148
1165
|
// text side wins. This is what makes ANY wallpaper survivable.
|
|
1149
1166
|
const dark = Boolean(document.body.hasAttribute && document.body.hasAttribute("data-ds-dark-theme"));
|
|
1167
|
+
const roundedLum = sampledLuminance !== null ? Math.round(sampledLuminance * 100) / 100 : null;
|
|
1150
1168
|
const key = [
|
|
1151
1169
|
dark, selection.scrim, selection.border, selection.blur, selection.wallpaperBlur,
|
|
1152
|
-
selection.autoScrim,
|
|
1170
|
+
selection.autoScrim, roundedLum, selection.fit, selection.zoom,
|
|
1153
1171
|
selection.offsetX, selection.offsetY, selection.rotation, selection.mirrored,
|
|
1154
1172
|
].join("\u0000");
|
|
1155
1173
|
if (key === lastEffectKey) return; // nothing it reads changed → no writes, no reflow
|
|
@@ -1200,9 +1218,6 @@ window.__ModuleLoader__.load({
|
|
|
1200
1218
|
// slider feedback lands on this frame even on stalled compositors.
|
|
1201
1219
|
const scrim = document.getElementById(SCRIM_ID);
|
|
1202
1220
|
if (scrim) scrim.style.background = veilColor;
|
|
1203
|
-
if (document.body && document.body.offsetHeight !== undefined) {
|
|
1204
|
-
void document.body.offsetHeight;
|
|
1205
|
-
}
|
|
1206
1221
|
}
|
|
1207
1222
|
|
|
1208
1223
|
function clearEffects() {
|
|
@@ -1242,7 +1257,7 @@ window.__ModuleLoader__.load({
|
|
|
1242
1257
|
}
|
|
1243
1258
|
onInput(v);
|
|
1244
1259
|
};
|
|
1245
|
-
return React.createElement(React.Fragment,
|
|
1260
|
+
return React.createElement(React.Fragment, { key: label },
|
|
1246
1261
|
React.createElement("span", { className: "webg-hint webg-label" }, label),
|
|
1247
1262
|
React.createElement("input", {
|
|
1248
1263
|
className: "webg-slider", type: "range",
|
|
@@ -1446,6 +1461,7 @@ window.__ModuleLoader__.load({
|
|
|
1446
1461
|
className: "webg-text webg-search", type: "search",
|
|
1447
1462
|
placeholder: t.searchPlaceholder,
|
|
1448
1463
|
value: query,
|
|
1464
|
+
onChange: (e) => setQuery(e.target.value),
|
|
1449
1465
|
onInput: (e) => setQuery(e.target.value),
|
|
1450
1466
|
}),
|
|
1451
1467
|
query.trim() && React.createElement("span", { className: "webg-hint" },
|
|
@@ -1476,14 +1492,14 @@ window.__ModuleLoader__.load({
|
|
|
1476
1492
|
React.createElement("span", { className: "webg-card-close" }, t.closeCard),
|
|
1477
1493
|
),
|
|
1478
1494
|
usableList.length === 0
|
|
1479
|
-
? React.createElement("span", { className: "webg-hint" },
|
|
1495
|
+
? React.createElement("span", { className: "webg-hint webg-grid-empty" },
|
|
1480
1496
|
sel.inventory.installDir
|
|
1481
1497
|
? (sel.inventory.total > 0
|
|
1482
1498
|
? t.emptyNoUsable(sel.inventory.total)
|
|
1483
1499
|
: t.emptyNoProjects)
|
|
1484
1500
|
: t.emptyNoInstall)
|
|
1485
1501
|
: filteredList.length === 0
|
|
1486
|
-
? React.createElement("span", { className: "webg-hint" }, t.noMatch(q))
|
|
1502
|
+
? React.createElement("span", { className: "webg-hint webg-grid-empty" }, t.noMatch(q))
|
|
1487
1503
|
: filteredList.map((w) => ThumbCard(w, w.id === sel.id, () => applySelection(w.id), t)),
|
|
1488
1504
|
);
|
|
1489
1505
|
}
|
|
@@ -1563,7 +1579,9 @@ window.__ModuleLoader__.load({
|
|
|
1563
1579
|
React.createElement("input", {
|
|
1564
1580
|
className: "webg-text", type: "text",
|
|
1565
1581
|
value: editing.name,
|
|
1566
|
-
|
|
1582
|
+
onChange: (e) => { editing.name = e.target.value; if (!e.nativeEvent || !e.nativeEvent.isComposing) emit(); },
|
|
1583
|
+
onInput: (e) => { editing.name = e.target.value; },
|
|
1584
|
+
onCompositionEnd: (e) => { editing.name = e.target.value; emit(); },
|
|
1567
1585
|
}),
|
|
1568
1586
|
),
|
|
1569
1587
|
React.createElement("div", { className: "webg-row" },
|
|
@@ -1588,6 +1606,7 @@ window.__ModuleLoader__.load({
|
|
|
1588
1606
|
className: "webg-text", type: "search",
|
|
1589
1607
|
placeholder: t.filterPlaceholder,
|
|
1590
1608
|
value: editorQuery,
|
|
1609
|
+
onChange: (e) => setEditorQuery(e.target.value),
|
|
1591
1610
|
onInput: (e) => setEditorQuery(e.target.value),
|
|
1592
1611
|
}),
|
|
1593
1612
|
React.createElement("div", { className: "webg-editor-grid" },
|
|
@@ -1595,10 +1614,10 @@ window.__ModuleLoader__.load({
|
|
|
1595
1614
|
const eq = editorQuery.trim();
|
|
1596
1615
|
const pool = usableList.filter((w) => matchesQuery(w, eq));
|
|
1597
1616
|
if (usableList.length === 0) {
|
|
1598
|
-
return React.createElement("span", { className: "webg-hint" }, t.noUsable);
|
|
1617
|
+
return React.createElement("span", { className: "webg-hint webg-grid-empty" }, t.noUsable);
|
|
1599
1618
|
}
|
|
1600
1619
|
if (pool.length === 0) {
|
|
1601
|
-
return React.createElement("span", { className: "webg-hint" }, t.noMatch(eq));
|
|
1620
|
+
return React.createElement("span", { className: "webg-hint webg-grid-empty" }, t.noMatch(eq));
|
|
1602
1621
|
}
|
|
1603
1622
|
return pool.map((w) => EditorCard(w, editing, t));
|
|
1604
1623
|
})(),
|
|
@@ -1685,7 +1704,7 @@ window.__ModuleLoader__.load({
|
|
|
1685
1704
|
className: "webg-btn", type: "button", onClick: enterAdjust,
|
|
1686
1705
|
disabled: sel.adjusting,
|
|
1687
1706
|
}, t.adjust),
|
|
1688
|
-
(sel.zoom !== 1 || sel.offsetX !== 0 || sel.offsetY !== 0) &&
|
|
1707
|
+
(sel.zoom !== 1 || sel.offsetX !== 0 || sel.offsetY !== 0 || sel.rotation !== 0) &&
|
|
1689
1708
|
React.createElement("button", {
|
|
1690
1709
|
className: "webg-btn", type: "button", onClick: resetCrop,
|
|
1691
1710
|
}, t.resetCrop),
|
|
@@ -2070,6 +2089,11 @@ window.__ModuleLoader__.load({
|
|
|
2070
2089
|
display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
|
2071
2090
|
gap: 8px; max-height: 300px; overflow-y: auto; padding: 2px;
|
|
2072
2091
|
}
|
|
2092
|
+
.webg-grid-empty {
|
|
2093
|
+
grid-column: 1 / -1;
|
|
2094
|
+
display: flex; align-items: center; justify-content: center;
|
|
2095
|
+
padding: 24px 12px; text-align: center;
|
|
2096
|
+
}
|
|
2073
2097
|
.webg-card {
|
|
2074
2098
|
position: relative; width: 100%; padding: 0; cursor: pointer;
|
|
2075
2099
|
aspect-ratio: 16 / 9; display: block; overflow: hidden;
|
|
@@ -2323,7 +2347,7 @@ window.__ModuleLoader__.load({
|
|
|
2323
2347
|
if (ctx.slots) {
|
|
2324
2348
|
ctx.slots.inject("settings.general.item", () =>
|
|
2325
2349
|
ctx.slots.register(
|
|
2326
|
-
{ name: "settings.general.item", id: "we-background", order: 500, label: S().settingsLabel },
|
|
2350
|
+
{ name: "settings.general.item", id: "we-background", order: 500, label: () => S().settingsLabel },
|
|
2327
2351
|
() => React.createElement(WallpaperPicker),
|
|
2328
2352
|
),
|
|
2329
2353
|
);
|
package/lib/core.js
CHANGED
|
@@ -174,8 +174,10 @@ export function steamProbeDirs(platform = process.platform, home = homedir) {
|
|
|
174
174
|
return [
|
|
175
175
|
'C:\\Program Files (x86)\\Steam',
|
|
176
176
|
'C:\\Program Files\\Steam',
|
|
177
|
+
'C:\\SteamLibrary',
|
|
177
178
|
'D:\\Steam',
|
|
178
179
|
'D:\\SteamLibrary',
|
|
180
|
+
'E:\\Steam',
|
|
179
181
|
'E:\\SteamLibrary',
|
|
180
182
|
];
|
|
181
183
|
case 'darwin':
|
|
@@ -536,9 +538,13 @@ export function mimeFor(absPath) {
|
|
|
536
538
|
js: 'text/javascript; charset=utf-8', mjs: 'text/javascript; charset=utf-8',
|
|
537
539
|
css: 'text/css; charset=utf-8', json: 'application/json; charset=utf-8',
|
|
538
540
|
jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif',
|
|
539
|
-
png: 'image/png', webp: 'image/webp', svg: 'image/svg+xml',
|
|
541
|
+
png: 'image/png', webp: 'image/webp', svg: 'image/svg+xml', ico: 'image/x-icon',
|
|
540
542
|
mp3: 'audio/mpeg', ogg: 'audio/ogg', wav: 'audio/wav',
|
|
543
|
+
flac: 'audio/flac', aac: 'audio/aac', m4a: 'audio/mp4',
|
|
541
544
|
woff: 'font/woff', woff2: 'font/woff2', ttf: 'font/ttf',
|
|
545
|
+
otf: 'font/otf', eot: 'application/vnd.ms-fontobject',
|
|
546
|
+
wasm: 'application/wasm', txt: 'text/plain; charset=utf-8',
|
|
547
|
+
xml: 'application/xml; charset=utf-8',
|
|
542
548
|
}[ext] || 'application/octet-stream';
|
|
543
549
|
}
|
|
544
550
|
|
package/lib/index.js
CHANGED
|
@@ -265,7 +265,7 @@ export function createRouteRegistrar(webServer, opts = {}) {
|
|
|
265
265
|
// unguessable token remains the only capability — wildcard origin
|
|
266
266
|
// grants nothing beyond what a known URL already grants.
|
|
267
267
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
268
|
-
if (mime
|
|
268
|
+
if (mime.startsWith('text/html') || mime === 'image/svg+xml') {
|
|
269
269
|
// Script-capable documents (web wallpapers, SVG previews) get a
|
|
270
270
|
// sandbox CSP even on direct top-level navigation, so they can
|
|
271
271
|
// never execute against the DSH origin. `allow-scripts` keeps the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallpaper-engine-dsh",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
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",
|