wallpaper-engine-dsh 1.0.0 → 1.0.2
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 -1
- package/README.zh.md +1 -1
- package/lib/client.js +33 -12
- package/lib/index.js +5 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ A DSH bundle that turns your local **Wallpaper Engine** library into the live ba
|
|
|
10
10
|
|
|
11
11
|
**Legibility on any wallpaper.** Text stays readable by construction, not by luck. The veil always opposes the text colour — black in the dark theme, white in the light theme — so neither a pitch-black nor a pure-white wallpaper can swallow the UI. On top of that, a Smart veil samples the wallpaper's brightness every few seconds and automatically strengthens the veil when a scene drifts too bright (or too dark) for the current theme; it also strengthens the border contrast and the glass frosting on the same evidence. Dropdowns, menus, and dialogs sit on DSH's opaque surfaces and are never affected.
|
|
12
12
|
|
|
13
|
-
**Manual framing.** Pick a base layout — Cover, Contain, Stretch, or Original — then frame the shot yourself. **Adjust** opens the live wallpaper fullscreen:
|
|
13
|
+
**Manual framing.** Pick a base layout — Cover, Contain, Stretch, or Original — then frame the shot yourself. **Adjust** opens the live wallpaper fullscreen: scroll to zoom in (up to 4×), drag to pan within the zoomed framing — the crop is clamped so the image always fills the screen with no exposed edges. Esc or Done finishes, the framing persists per selection, and **Reset crop** restores the default in one click.
|
|
14
14
|
|
|
15
15
|
**Four live sliders.** Wallpaper blur, Scrim, Borders, and Glass — every change lands instantly and persists. Wallpaper blur uses clipped overscan, so blurring never warps or shifts the image; a whisper of dither noise keeps smooth gradients band-free; and at zero blur the media bypasses the filter pipeline entirely for bit-exact pixels.
|
|
16
16
|
|
package/README.zh.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
**任意壁纸都可读。** 文字可读靠的是结构保障,不是运气。遮罩颜色始终与文字颜色相对——深色主题压黑、浅色主题提亮——无论纯黑还是纯白的壁纸都吞不掉界面。在此基础上,"智能可视"每隔几秒采样一次壁纸亮度,画面偏离当前主题的舒适区时自动加强遮罩。下拉菜单、弹窗等浮层坐在 DSH 原生的不透明表面上,从不受影响。
|
|
12
12
|
|
|
13
|
-
**手动取景。**
|
|
13
|
+
**手动取景。** 先选基础排布——填充、适应、拉伸、原始——然后自己构图:点「调整画面」把壁纸全屏展开,滚轮放大(最高 4×)、拖动在放大的画面内平移——裁剪范围经过钳制,画面永远铺满屏幕、不露边。Esc 或「完成」退出,取景随选择持久保存,「重置裁剪」一键还原。
|
|
14
14
|
|
|
15
15
|
**四个实时滑杆。** 壁纸模糊、暗化、边框、玻璃——每一步调节即时生效并持久保存。壁纸模糊采用裁边式超采样,模糊不变形、不偏移;叠加微量抖动噪声消除渐变色带;模糊归零时媒体完全绕开滤镜管线,像素逐位精确。
|
|
16
16
|
|
package/lib/client.js
CHANGED
|
@@ -271,7 +271,9 @@ window.__ModuleLoader__.load({
|
|
|
271
271
|
autoScrim: o.autoScrim !== false,
|
|
272
272
|
lang: o.lang === "zh" || o.lang === "en" ? o.lang : "auto",
|
|
273
273
|
fit: FIT_MODES.indexOf(o.fit) >= 0 ? o.fit : DEFAULTS.fit,
|
|
274
|
-
zoom: clampNum(o.zoom, 0.25, 4, DEFAULTS.zoom),
|
|
274
|
+
zoom: Math.max(1, clampNum(o.zoom, 0.25, 4, DEFAULTS.zoom)),
|
|
275
|
+
// Pan may have been persisted with a larger headroom than the zoom
|
|
276
|
+
// allows (older builds let zoom go below 1) — clampCrop re-seats it.
|
|
275
277
|
offsetX: clampNum(o.offsetX, -200, 200, DEFAULTS.offsetX),
|
|
276
278
|
offsetY: clampNum(o.offsetY, -200, 200, DEFAULTS.offsetY),
|
|
277
279
|
};
|
|
@@ -298,6 +300,9 @@ window.__ModuleLoader__.load({
|
|
|
298
300
|
inventory: { installDir: null, wallpapers: [], total: 0, portableCount: 0, playlists: [], error: null },
|
|
299
301
|
loaded: false,
|
|
300
302
|
};
|
|
303
|
+
// Older builds allowed zoom < 1 and unclamped pans — re-seat any persisted
|
|
304
|
+
// crop into the gap-free envelope before the first render.
|
|
305
|
+
clampCrop();
|
|
301
306
|
|
|
302
307
|
const listeners = new Set();
|
|
303
308
|
function emit() { for (const fn of [...listeners]) fn(); }
|
|
@@ -724,6 +729,18 @@ window.__ModuleLoader__.load({
|
|
|
724
729
|
// The layer normally sits at z-index -2 behind the entire app, so it can
|
|
725
730
|
// never receive pointer events. Adjust mode moves the LIVE layer node into a
|
|
726
731
|
// topmost transparent overlay — the user edits the real thing, WYSIWYG.
|
|
732
|
+
//
|
|
733
|
+
// Crop geometry invariants: the media box covers the viewport exactly at
|
|
734
|
+
// zoom 1; zooming creates headroom, panning spends it. Zoom floors at 1
|
|
735
|
+
// and pan is clamped to ±(zoom-1)/2·100 %, so a gap-free fullscreen image
|
|
736
|
+
// is guaranteed at every setting.
|
|
737
|
+
function clampCrop() {
|
|
738
|
+
selection.zoom = Math.round(Math.min(4, Math.max(1, selection.zoom)) * 100) / 100;
|
|
739
|
+
const pan = (selection.zoom - 1) * 50;
|
|
740
|
+
selection.offsetX = Math.min(pan, Math.max(-pan, selection.offsetX));
|
|
741
|
+
selection.offsetY = Math.min(pan, Math.max(-pan, selection.offsetY));
|
|
742
|
+
}
|
|
743
|
+
|
|
727
744
|
let adjustOverlay = null;
|
|
728
745
|
let adjustCleanup = null;
|
|
729
746
|
|
|
@@ -780,11 +797,9 @@ window.__ModuleLoader__.load({
|
|
|
780
797
|
// content tracks the cursor 1:1 at any blur setting.
|
|
781
798
|
const w = (overlay.clientWidth || 1) + 2 * selection.wallpaperBlur;
|
|
782
799
|
const h = (overlay.clientHeight || 1) + 2 * selection.wallpaperBlur;
|
|
783
|
-
|
|
784
|
-
selection.
|
|
785
|
-
|
|
786
|
-
selection.offsetY = Math.min(200, Math.max(-200,
|
|
787
|
-
selection.offsetY + ((e.clientY - drag.y) / h) * 100));
|
|
800
|
+
selection.offsetX += ((e.clientX - drag.x) / w) * 100;
|
|
801
|
+
selection.offsetY += ((e.clientY - drag.y) / h) * 100;
|
|
802
|
+
clampCrop(); // gap-free guarantee: pan never outruns the zoom headroom
|
|
788
803
|
drag = { x: e.clientX, y: e.clientY };
|
|
789
804
|
applyEffects();
|
|
790
805
|
};
|
|
@@ -802,12 +817,12 @@ window.__ModuleLoader__.load({
|
|
|
802
817
|
};
|
|
803
818
|
const onWheel = (e) => {
|
|
804
819
|
if (typeof e.preventDefault === "function") e.preventDefault();
|
|
805
|
-
//
|
|
806
|
-
//
|
|
807
|
-
//
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
820
|
+
// Crop semantics: zoom IN only (1–4×). Zooming below cover would float a
|
|
821
|
+
// shrunken box in empty space — that is not a crop. Tightening zoom also
|
|
822
|
+
// re-clamps the pan into the new headroom, so zooming back to 1 pulls
|
|
823
|
+
// the framing home instead of leaving edge gaps.
|
|
824
|
+
selection.zoom *= Math.exp(-(e.deltaY || 0) * 0.0012);
|
|
825
|
+
clampCrop();
|
|
811
826
|
applyEffects();
|
|
812
827
|
persistSelection();
|
|
813
828
|
};
|
|
@@ -1830,6 +1845,12 @@ window.__ModuleLoader__.load({
|
|
|
1830
1845
|
const inject = ["slots"];
|
|
1831
1846
|
|
|
1832
1847
|
function apply(ctx) {
|
|
1848
|
+
// A plugin UPDATE re-applies this module WITHOUT re-evaluating it: the old
|
|
1849
|
+
// fiber's cleanup has already set `disposed = true`, which would make the
|
|
1850
|
+
// new fiber's loadInventory return forever (blank picker, no wallpaper).
|
|
1851
|
+
// Every apply starts a fresh lifecycle.
|
|
1852
|
+
disposed = false;
|
|
1853
|
+
|
|
1833
1854
|
// 0. Language: follow the shell's locale service when present, and react
|
|
1834
1855
|
// to its change events. Everything is optional — without the service
|
|
1835
1856
|
// the browser language decides, and the manual override always wins.
|
package/lib/index.js
CHANGED
|
@@ -228,10 +228,11 @@ export function createRouteRegistrar(webServer, opts = {}) {
|
|
|
228
228
|
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
229
229
|
if (mime === 'text/html' || mime === 'image/svg+xml') {
|
|
230
230
|
// Script-capable documents (web wallpapers, SVG previews) get a
|
|
231
|
-
//
|
|
232
|
-
// never execute against the DSH origin.
|
|
233
|
-
//
|
|
234
|
-
|
|
231
|
+
// sandbox CSP even on direct top-level navigation, so they can
|
|
232
|
+
// never execute against the DSH origin. `allow-scripts` keeps the
|
|
233
|
+
// wallpaper itself functional — inside the sandbox the origin is
|
|
234
|
+
// opaque either way, so the isolation goal is unchanged.
|
|
235
|
+
res.setHeader('Content-Security-Policy', 'sandbox allow-scripts');
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
const range = core.parseRangeHeader(req.headers.range, st.size);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallpaper-engine-dsh",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
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",
|