dsh-dream-skin 0.2.2 → 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 +148 -6
- 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. */
|
|
@@ -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": "恢复主题色",
|
|
@@ -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")
|
|
@@ -1692,17 +1767,43 @@ window.__ModuleLoader__.load({
|
|
|
1692
1767
|
syncWallpaper();
|
|
1693
1768
|
}
|
|
1694
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
|
+
|
|
1695
1796
|
/** Set a wallpaper by kind and value. */
|
|
1696
1797
|
function setWallpaperKind(ctx, kind, value) {
|
|
1697
1798
|
writeStorage(WALLPAPER_KIND_KEY, kind);
|
|
1698
1799
|
if (kind === "gradient") {
|
|
1699
1800
|
writeStorage(WALLPAPER_GRADIENT_KEY, value);
|
|
1700
|
-
if (value === null) writeStorage(WALLPAPER_GRADIENT_KEY, null);
|
|
1701
1801
|
} else if (kind === "url") {
|
|
1702
1802
|
writeStorage(WALLPAPER_URL_KEY, value);
|
|
1703
1803
|
} else {
|
|
1704
1804
|
writeStorage(WALLPAPER_KEY, value);
|
|
1705
1805
|
}
|
|
1806
|
+
pushWallpaperHistory(kind, value);
|
|
1706
1807
|
applyWallpaper2(ctx);
|
|
1707
1808
|
syncWallpaper();
|
|
1708
1809
|
}
|
|
@@ -1735,6 +1836,13 @@ window.__ModuleLoader__.load({
|
|
|
1735
1836
|
//#endregion
|
|
1736
1837
|
|
|
1737
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
|
+
|
|
1738
1846
|
/**
|
|
1739
1847
|
* Accent row: pick an arbitrary brand-accent color (or clear to follow
|
|
1740
1848
|
* the active theme). Uses an `<input type="color">` + the current accent
|
|
@@ -1778,6 +1886,21 @@ window.__ModuleLoader__.load({
|
|
|
1778
1886
|
}) : null
|
|
1779
1887
|
]
|
|
1780
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
|
+
}),
|
|
1781
1904
|
(0, react_jsx_runtime.jsx)("div", {
|
|
1782
1905
|
style: styles.hint,
|
|
1783
1906
|
children: t("accent.hint")
|
|
@@ -1968,7 +2091,13 @@ window.__ModuleLoader__.load({
|
|
|
1968
2091
|
wallpaperRevision += 1;
|
|
1969
2092
|
// Store the raw data URL (not the CSS url(...) wrapper) so the
|
|
1970
2093
|
// Wallpaper row can render an <img> preview and test `url !== null`.
|
|
1971
|
-
wallpaperBound?.sync(
|
|
2094
|
+
wallpaperBound?.sync(
|
|
2095
|
+
readWallpaper(),
|
|
2096
|
+
readWallpaperOpacity(),
|
|
2097
|
+
readWallpaperBlur(),
|
|
2098
|
+
readWallpaperHistory(),
|
|
2099
|
+
wallpaperRevision
|
|
2100
|
+
);
|
|
1972
2101
|
};
|
|
1973
2102
|
applyWallpaper2(ctx);
|
|
1974
2103
|
syncWallpaper();
|
|
@@ -1998,6 +2127,11 @@ window.__ModuleLoader__.load({
|
|
|
1998
2127
|
setSkin: (id) => {
|
|
1999
2128
|
ctx.theme.setTheme(id);
|
|
2000
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);
|
|
2001
2135
|
}
|
|
2002
2136
|
};
|
|
2003
2137
|
};
|
|
@@ -2043,6 +2177,14 @@ window.__ModuleLoader__.load({
|
|
|
2043
2177
|
applyWallpaper2(ctx);
|
|
2044
2178
|
syncWallpaper();
|
|
2045
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
|
+
},
|
|
2046
2188
|
clearWallpaper: () => {
|
|
2047
2189
|
removeWallpaper(ctx);
|
|
2048
2190
|
}
|
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",
|