dsh-dream-skin 0.2.1 → 0.2.3
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 +162 -11
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -36,6 +36,10 @@ window.__ModuleLoader__.load({
|
|
|
36
36
|
const WALLPAPER_OPACITY_KEY = "dsh-dream-skin:wallpaper-opacity";
|
|
37
37
|
/** localStorage key holding the wallpaper blur radius (px). */
|
|
38
38
|
const WALLPAPER_BLUR_KEY = "dsh-dream-skin:wallpaper-blur";
|
|
39
|
+
/** localStorage key holding recent wallpaper history (JSON array of {kind,value}). */
|
|
40
|
+
const WALLPAPER_HISTORY_KEY = "dsh-dream-skin:wallpaper-history";
|
|
41
|
+
/** Max wallpaper history entries kept. */
|
|
42
|
+
const WALLPAPER_HISTORY_MAX = 5;
|
|
39
43
|
/** Sentinel meaning "no custom skin — follow the built-in appearance". */
|
|
40
44
|
const DEFAULT_SKIN = "system";
|
|
41
45
|
/** Default wash opacity (0..1) applied to the translucent surfaces. */
|
|
@@ -328,7 +332,7 @@ window.__ModuleLoader__.load({
|
|
|
328
332
|
|
|
329
333
|
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
330
334
|
const zh = {
|
|
331
|
-
"skin.title": "
|
|
335
|
+
"skin.title": "皮肤",
|
|
332
336
|
"skin.default": "默认",
|
|
333
337
|
"skin.abyss": "深海渊",
|
|
334
338
|
"skin.aurora": "极光",
|
|
@@ -344,6 +348,8 @@ window.__ModuleLoader__.load({
|
|
|
344
348
|
"background.opacity": "透明度",
|
|
345
349
|
"background.blur": "模糊",
|
|
346
350
|
"background.hint": "图片显示在主内容区与侧边栏的半透明底上,消息等内层表面保持不透明以保证可读性",
|
|
351
|
+
"background.history": "最近使用",
|
|
352
|
+
"background.historyApply": "点击换回这张壁纸",
|
|
347
353
|
"accent.title": "强调色(Accent)",
|
|
348
354
|
"accent.random": "随机",
|
|
349
355
|
"accent.clear": "恢复主题色",
|
|
@@ -365,7 +371,7 @@ window.__ModuleLoader__.load({
|
|
|
365
371
|
|
|
366
372
|
/** English dictionary, checked complete against the zh key set. */
|
|
367
373
|
const en = {
|
|
368
|
-
"skin.title": "Skins
|
|
374
|
+
"skin.title": "Skins",
|
|
369
375
|
"skin.default": "Default",
|
|
370
376
|
"skin.abyss": "Abyss",
|
|
371
377
|
"skin.aurora": "Aurora",
|
|
@@ -381,6 +387,8 @@ window.__ModuleLoader__.load({
|
|
|
381
387
|
"background.opacity": "Opacity",
|
|
382
388
|
"background.blur": "Blur",
|
|
383
389
|
"background.hint": "The image shows through the translucent main canvas and sidebar; inner surfaces stay opaque for readability",
|
|
390
|
+
"background.history": "Recent",
|
|
391
|
+
"background.historyApply": "Click to switch back",
|
|
384
392
|
"accent.title": "Accent",
|
|
385
393
|
"accent.random": "Random",
|
|
386
394
|
"accent.clear": "Reset to theme",
|
|
@@ -612,14 +620,16 @@ window.__ModuleLoader__.load({
|
|
|
612
620
|
url: null,
|
|
613
621
|
opacity: DEFAULT_WALLPAPER_OPACITY,
|
|
614
622
|
blur: DEFAULT_WALLPAPER_BLUR,
|
|
623
|
+
history: [],
|
|
615
624
|
revision: -1
|
|
616
625
|
}),
|
|
617
626
|
actions: {
|
|
618
|
-
sync: (d, url, opacity, blur, revision) => {
|
|
627
|
+
sync: (d, url, opacity, blur, history, revision) => {
|
|
619
628
|
if (revision <= d.revision) return;
|
|
620
629
|
d.url = url;
|
|
621
630
|
d.opacity = opacity;
|
|
622
631
|
d.blur = blur;
|
|
632
|
+
d.history = history;
|
|
623
633
|
d.revision = revision;
|
|
624
634
|
}
|
|
625
635
|
}
|
|
@@ -665,11 +675,26 @@ window.__ModuleLoader__.load({
|
|
|
665
675
|
background: "transparent",
|
|
666
676
|
cursor: "pointer",
|
|
667
677
|
font: "inherit",
|
|
668
|
-
boxSizing: "border-box"
|
|
678
|
+
boxSizing: "border-box",
|
|
679
|
+
position: "relative"
|
|
669
680
|
},
|
|
670
681
|
cardSelected: {
|
|
671
682
|
borderColor: "var(--dsw-alias-brand-primary)",
|
|
672
|
-
background: "
|
|
683
|
+
background: "rgba(127, 127, 127, 0.10)"
|
|
684
|
+
},
|
|
685
|
+
cardCheck: {
|
|
686
|
+
position: "absolute",
|
|
687
|
+
top: "-4px",
|
|
688
|
+
right: "-4px",
|
|
689
|
+
width: "18px",
|
|
690
|
+
height: "18px",
|
|
691
|
+
borderRadius: "50%",
|
|
692
|
+
background: "var(--dsw-alias-brand-primary)",
|
|
693
|
+
color: "#ffffff",
|
|
694
|
+
fontSize: "12px",
|
|
695
|
+
lineHeight: "18px",
|
|
696
|
+
textAlign: "center",
|
|
697
|
+
fontWeight: 700
|
|
673
698
|
},
|
|
674
699
|
cardLabel: {
|
|
675
700
|
color: "var(--dsw-alias-label-secondary)",
|
|
@@ -756,6 +781,26 @@ window.__ModuleLoader__.load({
|
|
|
756
781
|
cursor: "pointer",
|
|
757
782
|
padding: 0
|
|
758
783
|
},
|
|
784
|
+
historyThumb: {
|
|
785
|
+
width: "56px",
|
|
786
|
+
height: "36px",
|
|
787
|
+
borderRadius: "8px",
|
|
788
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
789
|
+
cursor: "pointer",
|
|
790
|
+
padding: 0,
|
|
791
|
+
boxSizing: "border-box",
|
|
792
|
+
backgroundSize: "cover",
|
|
793
|
+
backgroundPosition: "center"
|
|
794
|
+
},
|
|
795
|
+
accentPreset: {
|
|
796
|
+
width: "24px",
|
|
797
|
+
height: "24px",
|
|
798
|
+
borderRadius: "50%",
|
|
799
|
+
border: "1px solid rgba(128,128,128,0.4)",
|
|
800
|
+
cursor: "pointer",
|
|
801
|
+
padding: 0,
|
|
802
|
+
boxSizing: "border-box"
|
|
803
|
+
},
|
|
759
804
|
checkbox: {
|
|
760
805
|
accentColor: "var(--dsw-alias-brand-primary)",
|
|
761
806
|
width: "16px",
|
|
@@ -857,6 +902,10 @@ window.__ModuleLoader__.load({
|
|
|
857
902
|
...(selected ? styles.cardSelected : {})
|
|
858
903
|
},
|
|
859
904
|
children: [
|
|
905
|
+
selected ? (0, react_jsx_runtime.jsx)("span", {
|
|
906
|
+
style: styles.cardCheck,
|
|
907
|
+
children: "✓"
|
|
908
|
+
}) : null,
|
|
860
909
|
(0, react_jsx_runtime.jsx)(Swatch, { tokens: skin.tokens }),
|
|
861
910
|
(0, react_jsx_runtime.jsx)("span", {
|
|
862
911
|
style: {
|
|
@@ -948,10 +997,11 @@ window.__ModuleLoader__.load({
|
|
|
948
997
|
* Wallpaper row: choose (compressed to a data URL), preview, tune the
|
|
949
998
|
* wash opacity and blur, and remove the wallpaper.
|
|
950
999
|
*/
|
|
951
|
-
function WallpaperRow({ t, setWallpaper, setOpacity, setBlur, useStore }) {
|
|
1000
|
+
function WallpaperRow({ t, setWallpaper, setOpacity, setBlur, applyFromHistory, useStore }) {
|
|
952
1001
|
const url = useStore((s) => s.url);
|
|
953
1002
|
const opacity = useStore((s) => s.opacity);
|
|
954
1003
|
const blur = useStore((s) => s.blur);
|
|
1004
|
+
const history = useStore((s) => s.history);
|
|
955
1005
|
const inputRef = (0, _react.useRef)(null);
|
|
956
1006
|
const onPick = () => inputRef.current?.click();
|
|
957
1007
|
const onFile = (event) => {
|
|
@@ -1019,6 +1069,31 @@ window.__ModuleLoader__.load({
|
|
|
1019
1069
|
format: (v) => `${v}px`,
|
|
1020
1070
|
onChange: setBlur
|
|
1021
1071
|
}),
|
|
1072
|
+
history && history.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
1073
|
+
style: { ...styles.group, padding: "8px 0", borderBottom: "none" },
|
|
1074
|
+
children: [
|
|
1075
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
1076
|
+
style: styles.title,
|
|
1077
|
+
children: t("background.history")
|
|
1078
|
+
}),
|
|
1079
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1080
|
+
style: styles.actionRow,
|
|
1081
|
+
children: history.map((entry, i) => {
|
|
1082
|
+
const isImage = entry.kind !== "gradient" && entry.kind !== "url";
|
|
1083
|
+
return (0, react_jsx_runtime.jsx)("button", {
|
|
1084
|
+
type: "button",
|
|
1085
|
+
title: t("background.historyApply"),
|
|
1086
|
+
style: {
|
|
1087
|
+
...styles.historyThumb,
|
|
1088
|
+
background: isImage ? `url("${entry.value}") center/cover no-repeat` : entry.value
|
|
1089
|
+
},
|
|
1090
|
+
onClick: () => applyFromHistory(entry.kind, entry.value),
|
|
1091
|
+
children: null
|
|
1092
|
+
}, i);
|
|
1093
|
+
})
|
|
1094
|
+
})
|
|
1095
|
+
]
|
|
1096
|
+
}) : null,
|
|
1022
1097
|
(0, react_jsx_runtime.jsx)("div", {
|
|
1023
1098
|
style: styles.hint,
|
|
1024
1099
|
children: t("background.hint")
|
|
@@ -1098,6 +1173,7 @@ window.__ModuleLoader__.load({
|
|
|
1098
1173
|
"aria-pressed": gradient === g,
|
|
1099
1174
|
style: {
|
|
1100
1175
|
...styles.presetswatches,
|
|
1176
|
+
background: g,
|
|
1101
1177
|
...(gradient === g ? { outline: "2px solid var(--dsw-alias-brand-primary)" } : {})
|
|
1102
1178
|
},
|
|
1103
1179
|
onClick: () => setGradient(g),
|
|
@@ -1691,17 +1767,43 @@ window.__ModuleLoader__.load({
|
|
|
1691
1767
|
syncWallpaper();
|
|
1692
1768
|
}
|
|
1693
1769
|
|
|
1770
|
+
/** Read recent wallpaper history entries [{kind,value}]. */
|
|
1771
|
+
function readWallpaperHistory() {
|
|
1772
|
+
const raw = readStorage(WALLPAPER_HISTORY_KEY);
|
|
1773
|
+
if (raw === null) return [];
|
|
1774
|
+
try {
|
|
1775
|
+
const parsed = JSON.parse(raw);
|
|
1776
|
+
return Array.isArray(parsed) ? parsed.filter((e) => e && typeof e.value === "string") : [];
|
|
1777
|
+
} catch {
|
|
1778
|
+
return [];
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
/** Persist the wallpaper history list. */
|
|
1783
|
+
function writeWallpaperHistory(list) {
|
|
1784
|
+
writeStorage(WALLPAPER_HISTORY_KEY, JSON.stringify(list.slice(0, WALLPAPER_HISTORY_MAX)));
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
/** Record a wallpaper setting into history (dedupe by kind+value, newest first). */
|
|
1788
|
+
function pushWallpaperHistory(kind, value) {
|
|
1789
|
+
if (value === null || value === undefined || value === "") return;
|
|
1790
|
+
const list = readWallpaperHistory();
|
|
1791
|
+
const deduped = list.filter((e) => !(e.kind === kind && e.value === value));
|
|
1792
|
+
deduped.unshift({ kind, value });
|
|
1793
|
+
writeWallpaperHistory(deduped);
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1694
1796
|
/** Set a wallpaper by kind and value. */
|
|
1695
1797
|
function setWallpaperKind(ctx, kind, value) {
|
|
1696
1798
|
writeStorage(WALLPAPER_KIND_KEY, kind);
|
|
1697
1799
|
if (kind === "gradient") {
|
|
1698
1800
|
writeStorage(WALLPAPER_GRADIENT_KEY, value);
|
|
1699
|
-
if (value === null) writeStorage(WALLPAPER_GRADIENT_KEY, null);
|
|
1700
1801
|
} else if (kind === "url") {
|
|
1701
1802
|
writeStorage(WALLPAPER_URL_KEY, value);
|
|
1702
1803
|
} else {
|
|
1703
1804
|
writeStorage(WALLPAPER_KEY, value);
|
|
1704
1805
|
}
|
|
1806
|
+
pushWallpaperHistory(kind, value);
|
|
1705
1807
|
applyWallpaper2(ctx);
|
|
1706
1808
|
syncWallpaper();
|
|
1707
1809
|
}
|
|
@@ -1734,6 +1836,13 @@ window.__ModuleLoader__.load({
|
|
|
1734
1836
|
//#endregion
|
|
1735
1837
|
|
|
1736
1838
|
//#region dsh-dream-skin: P0 UI rows (accent + packs)
|
|
1839
|
+
/** Curated accent presets users can pick with one click. */
|
|
1840
|
+
const ACCENT_PRESETS = [
|
|
1841
|
+
"#4f83f2", "#2563eb", "#34d399", "#22d3ee", "#a78bfa",
|
|
1842
|
+
"#fb923c", "#f87171", "#fbbf24", "#e879f9", "#f472b6",
|
|
1843
|
+
"#2dd4bf", "#a3e635"
|
|
1844
|
+
];
|
|
1845
|
+
|
|
1737
1846
|
/**
|
|
1738
1847
|
* Accent row: pick an arbitrary brand-accent color (or clear to follow
|
|
1739
1848
|
* the active theme). Uses an `<input type="color">` + the current accent
|
|
@@ -1777,6 +1886,21 @@ window.__ModuleLoader__.load({
|
|
|
1777
1886
|
}) : null
|
|
1778
1887
|
]
|
|
1779
1888
|
}),
|
|
1889
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1890
|
+
style: styles.actionRow,
|
|
1891
|
+
children: ACCENT_PRESETS.map((hex) => (0, react_jsx_runtime.jsx)("button", {
|
|
1892
|
+
type: "button",
|
|
1893
|
+
title: hex,
|
|
1894
|
+
"aria-pressed": activeValue === hex,
|
|
1895
|
+
style: {
|
|
1896
|
+
...styles.accentPreset,
|
|
1897
|
+
background: hex,
|
|
1898
|
+
...(activeValue === hex ? { outline: "2px solid var(--dsw-alias-label-primary)", outlineOffset: "1px" } : {})
|
|
1899
|
+
},
|
|
1900
|
+
onClick: () => setAccent(hex),
|
|
1901
|
+
children: null
|
|
1902
|
+
}, hex))
|
|
1903
|
+
}),
|
|
1780
1904
|
(0, react_jsx_runtime.jsx)("div", {
|
|
1781
1905
|
style: styles.hint,
|
|
1782
1906
|
children: t("accent.hint")
|
|
@@ -1967,7 +2091,13 @@ window.__ModuleLoader__.load({
|
|
|
1967
2091
|
wallpaperRevision += 1;
|
|
1968
2092
|
// Store the raw data URL (not the CSS url(...) wrapper) so the
|
|
1969
2093
|
// Wallpaper row can render an <img> preview and test `url !== null`.
|
|
1970
|
-
wallpaperBound?.sync(
|
|
2094
|
+
wallpaperBound?.sync(
|
|
2095
|
+
readWallpaper(),
|
|
2096
|
+
readWallpaperOpacity(),
|
|
2097
|
+
readWallpaperBlur(),
|
|
2098
|
+
readWallpaperHistory(),
|
|
2099
|
+
wallpaperRevision
|
|
2100
|
+
);
|
|
1971
2101
|
};
|
|
1972
2102
|
applyWallpaper2(ctx);
|
|
1973
2103
|
syncWallpaper();
|
|
@@ -1997,6 +2127,11 @@ window.__ModuleLoader__.load({
|
|
|
1997
2127
|
setSkin: (id) => {
|
|
1998
2128
|
ctx.theme.setTheme(id);
|
|
1999
2129
|
writeSavedSkin(id);
|
|
2130
|
+
// Deterministically push the new preference into the slot store AND
|
|
2131
|
+
// re-shade the wallpaper so the selected card follows immediately,
|
|
2132
|
+
// independent of theme/change emission timing.
|
|
2133
|
+
skinBound?.sync(id, (ctx.theme.getTheme().revision));
|
|
2134
|
+
if (wallpaperBackgroundCss() !== null) applyWallpaper2(ctx);
|
|
2000
2135
|
}
|
|
2001
2136
|
};
|
|
2002
2137
|
};
|
|
@@ -2042,6 +2177,14 @@ window.__ModuleLoader__.load({
|
|
|
2042
2177
|
applyWallpaper2(ctx);
|
|
2043
2178
|
syncWallpaper();
|
|
2044
2179
|
},
|
|
2180
|
+
applyFromHistory: (kind, value) => {
|
|
2181
|
+
const resolvedKind = kind === "gradient" || kind === "url" ? kind : "image";
|
|
2182
|
+
if (value && value.length > 4) {
|
|
2183
|
+
setWallpaperKind(ctx, resolvedKind, value);
|
|
2184
|
+
} else {
|
|
2185
|
+
syncWallpaper();
|
|
2186
|
+
}
|
|
2187
|
+
},
|
|
2045
2188
|
clearWallpaper: () => {
|
|
2046
2189
|
removeWallpaper(ctx);
|
|
2047
2190
|
}
|
|
@@ -2110,6 +2253,7 @@ window.__ModuleLoader__.load({
|
|
|
2110
2253
|
// P0: per-user accent override row.
|
|
2111
2254
|
const accentStore = createAccentStore();
|
|
2112
2255
|
let accentBound;
|
|
2256
|
+
let accentRevision = 0;
|
|
2113
2257
|
const accentInjected = (actions) => {
|
|
2114
2258
|
accentBound = actions;
|
|
2115
2259
|
const base = resolveAccent(ctx.theme.getTheme()) || DEFAULT_ACCENT;
|
|
@@ -2117,12 +2261,19 @@ window.__ModuleLoader__.load({
|
|
|
2117
2261
|
return {
|
|
2118
2262
|
setAccent: (value) => {
|
|
2119
2263
|
const applied = setAccent(ctx, value === DEFAULT_ACCENT ? null : value);
|
|
2120
|
-
accentBound?.sync(
|
|
2264
|
+
accentBound?.sync(
|
|
2265
|
+
applied || DEFAULT_ACCENT,
|
|
2266
|
+
resolveAccent(ctx.theme.getTheme()) || DEFAULT_ACCENT,
|
|
2267
|
+
++accentRevision
|
|
2268
|
+
);
|
|
2121
2269
|
},
|
|
2122
2270
|
clearAccent: () => {
|
|
2123
2271
|
setAccent(ctx, null);
|
|
2124
|
-
accentBound?.sync(
|
|
2125
|
-
|
|
2272
|
+
accentBound?.sync(
|
|
2273
|
+
DEFAULT_ACCENT,
|
|
2274
|
+
resolveAccent(ctx.theme.getTheme()) || DEFAULT_ACCENT,
|
|
2275
|
+
++accentRevision
|
|
2276
|
+
);
|
|
2126
2277
|
}
|
|
2127
2278
|
};
|
|
2128
2279
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-dream-skin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "DeepSeek Harness 换肤插件 (Dream Skin for DeepSeek Harness): curated --dsw-alias-* theme presets, a custom translucent wallpaper with opacity/blur controls, theme-pack import/export + share links, per-user accent, favorites & surprise-me, and durable per-browser persistence — in the spirit of the Codex Dream Skin project.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|