dsh-dream-skin 0.2.0 → 0.2.1

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.en.md CHANGED
@@ -24,6 +24,11 @@ Native skinning + wallpaper + theme packs — a romance-engineered project built
24
24
 
25
25
  </div>
26
26
 
27
+ > 🚀 **Now on npm!** With DSH installed, add it in one command — no cloning needed:
28
+ > ```sh
29
+ > dsh plugin --profile web add dsh-dream-skin
30
+ > ```
31
+
27
32
  > **Homage to [Codex-Dream-Skin](https://github.com/Fei-Away/Codex-Dream-Skin).** But the approach is different:
28
33
  > Codex injects CSS into the desktop client's renderer via CDP, whereas DSH is a **token-driven Web GUI** that ships
29
34
  > first-class "third-party plugins registering themes". So this plugin is **purely native** — no injection, no binary
@@ -74,13 +79,13 @@ Differentiation inspired by existing DSH skin projects plus Codex's skin UX:
74
79
 
75
80
  ```sh
76
81
  # 1. install
77
- dsh plugin --profile web add -w dsh-dream-skin
82
+ dsh plugin --profile web add dsh-dream-skin
78
83
  # 2. restart
79
84
  dsh web
80
85
  # 3. open Settings → General → Skins and pick one → done.
81
86
  ```
82
87
 
83
- > `-w` (workspace) is required because every profile ships a `pnpm-workspace.yaml`.
88
+ > Installs the published npm package — no cloning. If `dsh plugin add` reports a workspace error, append `-w`.
84
89
 
85
90
  ## 🧩 What kind of plugin is this
86
91
 
@@ -139,16 +144,12 @@ system.
139
144
 
140
145
  ## 📦 Install
141
146
 
142
-
143
- ### Option A: From source / a local directory
147
+ ### Option A: From npm (published, **recommended**)
144
148
 
145
149
  ```sh
146
- dsh plugin --profile web add -w /path/to/dsh-dream-skin
150
+ dsh plugin --profile web add dsh-dream-skin
147
151
  ```
148
152
 
149
- > The `-w` flag is **required**: every profile ships a `pnpm-workspace.yaml`, so pnpm treats the profile directory
150
- > as a workspace root and a bare `add` fails with `ERR_PNPM_ADDING_TO_ROOT`.
151
-
152
153
  Then **restart** the web server:
153
154
 
154
155
  ```sh
@@ -158,10 +159,14 @@ dsh web
158
159
 
159
160
  Open **Settings → General** to see the **Skins**, **Accent**, **Wallpaper** / **Advanced Wallpaper**, and **Theme Packs** rows.
160
161
 
161
- ### Option B: From npm (after publishing)
162
+ > The `-w` (workspace) flag is needed on a bare `add` because every profile ships a `pnpm-workspace.yaml`; pnpm treats
163
+ > the profile directory as a workspace root, so a bare add fails with `ERR_PNPM_ADDING_TO_ROOT`. If your profile already
164
+ > uses the workspace, you won't need to repeat it.
165
+
166
+ ### Option B: From source / a local directory (developers)
162
167
 
163
168
  ```sh
164
- dsh plugin --profile web add -w dsh-dream-skin
169
+ dsh plugin --profile web add -w /path/to/dsh-dream-skin
165
170
  ```
166
171
 
167
172
  ## 🧩 Compatibility
package/README.md CHANGED
@@ -24,6 +24,11 @@
24
24
 
25
25
  </div>
26
26
 
27
+ > 🚀 **现已发布到 npm!** 装好 DSH 后,一条命令即可安装,无需 clone:
28
+ > ```sh
29
+ > dsh plugin --profile web add dsh-dream-skin
30
+ > ```
31
+
27
32
  > **致敬 [Codex-Dream-Skin](https://github.com/Fei-Away/Codex-Dream-Skin)。** 但实现路径不同:Codex 是往桌面客户端渲染进程
28
33
  > 注入 CSS(CDP),而 DSH 本身是 **token 驱动的 Web GUI**,官方就提供了「第三方插件注册主题」的能力——所以本插件是
29
34
  > **纯原生接入**,无注入、不改二进制、不因客户端更新失效。
@@ -126,25 +131,22 @@ DeepSeek Harness 的口号是「一切皆插件」:模型、工具、沙箱、
126
131
 
127
132
  ```sh
128
133
  # 1. 安装
129
- dsh plugin --profile web add -w dsh-dream-skin
134
+ dsh plugin --profile web add dsh-dream-skin
130
135
  # 2. 重启
131
136
  dsh web
132
137
  # 3. 打开 设置 → 常规 → 皮肤,挑一套 → 完。
133
138
  ```
134
139
 
135
- > 传入 `-w`(workspace)是因为每个 profile 自带 `pnpm-workspace.yaml`,pnpm 需要知道这是 workspace 安装。
140
+ > 装的是 npm 已完成发布的正式包,无需 clone。若 `dsh plugin add` 报 workspace 相关错误,补一个 `-w` 即可。
136
141
 
137
142
  ## 📦 安装
138
143
 
139
- ### 方式一:从源码 / 本地目录
144
+ ### 方式一:npm(已发布,**推荐**)
140
145
 
141
146
  ```sh
142
- dsh plugin --profile web add -w /path/to/dsh-dream-skin
147
+ dsh plugin --profile web add dsh-dream-skin
143
148
  ```
144
149
 
145
- > `-w` 标志**必需**:每个 profile 自带 `pnpm-workspace.yaml`,pnpm 会把它当作 workspace 根,裸 `add` 会报
146
- > `ERR_PNPM_ADDING_TO_ROOT`。
147
-
148
150
  然后**重启** web 服务:
149
151
 
150
152
  ```sh
@@ -154,10 +156,13 @@ dsh web
154
156
 
155
157
  打开 **设置 → 常规**,即可看到「皮肤」「强调色」「背景图片 / 高级壁纸」与「主题包」等行。
156
158
 
157
- ### 方式二:npm 安装(发布后)
159
+ > `-w` 标志在裸 `add` 时必需:每个 profile 自带 `pnpm-workspace.yaml`,pnpm 会把它当作 workspace 根,裸加报错
160
+ > `ERR_PNPM_ADDING_TO_ROOT`。若已加过 `-w`,后续用现有 workspace 即无需重复。
161
+
162
+ ### 方式二:从源码 / 本地目录(开发者)
158
163
 
159
164
  ```sh
160
- dsh plugin --profile web add -w dsh-dream-skin
165
+ dsh plugin --profile web add -w /path/to/dsh-dream-skin
161
166
  ```
162
167
 
163
168
  ## 🧩 兼容性
package/lib/client.js CHANGED
@@ -1629,26 +1629,39 @@ window.__ModuleLoader__.load({
1629
1629
  return data ? `url("${data}")` : null;
1630
1630
  }
1631
1631
 
1632
+ /** Guards against re-entrant wallp-paper re-shading (overrideTokens emits theme/change). */
1633
+ let _applyingWallpaper = false;
1634
+
1632
1635
  /** Re-render the wallpaper backdrop from the current config. */
1633
1636
  function applyWallpaper2(ctx) {
1634
- const bg = wallpaperBackgroundCss();
1635
- const urlIsSet = bg !== null;
1636
- if (!urlIsSet) {
1637
- teardownWallpaper();
1638
- return;
1639
- }
1640
- if (wallpaperEl === null || !document.body.contains(wallpaperEl)) {
1641
- wallpaperEl = document.createElement("div");
1642
- wallpaperEl.style.cssText = "position:fixed;inset:0;z-index:-1;pointer-events:none;background-size:cover;background-position:center;background-repeat:no-repeat;";
1643
- document.body.prepend(wallpaperEl);
1637
+ // Re-entrancy guard: overrideTokens() below emits `theme/change`, which our
1638
+ // syncSkin listener would answer by calling applyWallpaper2 again — that
1639
+ // recursion would overflow the stack. Applying while already applying is a
1640
+ // no-op; the first (outermost) call performs the shading.
1641
+ if (_applyingWallpaper) return;
1642
+ _applyingWallpaper = true;
1643
+ try {
1644
+ const bg = wallpaperBackgroundCss();
1645
+ const urlIsSet = bg !== null;
1646
+ if (!urlIsSet) {
1647
+ teardownWallpaper();
1648
+ return;
1649
+ }
1650
+ if (wallpaperEl === null || !document.body.contains(wallpaperEl)) {
1651
+ wallpaperEl = document.createElement("div");
1652
+ wallpaperEl.style.cssText = "position:fixed;inset:0;z-index:-1;pointer-events:none;background-size:cover;background-position:center;background-repeat:no-repeat;";
1653
+ document.body.prepend(wallpaperEl);
1654
+ }
1655
+ const blur = readWallpaperBlur();
1656
+ wallpaperEl.style.backgroundImage = bg;
1657
+ wallpaperEl.style.filter = blur > 0 ? `blur(${blur}px)` : "none";
1658
+ // Auto-dim lowers the wash opacity when enabled.
1659
+ const baseFill = readWallpaperOpacity();
1660
+ const wash = readWallpaperAutodim() ? Math.min(baseFill, 0.45) : baseFill;
1661
+ shadeTokens2(ctx, wash, wash);
1662
+ } finally {
1663
+ _applyingWallpaper = false;
1644
1664
  }
1645
- const blur = readWallpaperBlur();
1646
- wallpaperEl.style.backgroundImage = bg;
1647
- wallpaperEl.style.filter = blur > 0 ? `blur(${blur}px)` : "none";
1648
- // Auto-dim lowers the wash opacity when enabled.
1649
- const baseFill = readWallpaperOpacity();
1650
- const wash = readWallpaperAutodim() ? Math.min(baseFill, 0.45) : baseFill;
1651
- shadeTokens2(ctx, wash, wash);
1652
1665
  }
1653
1666
 
1654
1667
  /** Like the original shadeTokens but with configurable alphas for the wash. */
@@ -1730,6 +1743,7 @@ window.__ModuleLoader__.load({
1730
1743
  const accent = useStore((s) => s.accent);
1731
1744
  const base = useStore((s) => s.base);
1732
1745
  const activeValue = accent !== DEFAULT_ACCENT ? accent : base;
1746
+ const inputValue = normalizeHex(activeValue) || "#4f83f2";
1733
1747
  return (0, react_jsx_runtime.jsxs)("div", {
1734
1748
  style: styles.group,
1735
1749
  children: [
@@ -1742,7 +1756,7 @@ window.__ModuleLoader__.load({
1742
1756
  children: [
1743
1757
  (0, react_jsx_runtime.jsx)("input", {
1744
1758
  type: "color",
1745
- value: (0, _react.useMemo)(() => normalizeHex(activeValue) || "#4f83f2", [activeValue]),
1759
+ value: inputValue,
1746
1760
  style: { ...styles.swatch, width: "40px", height: "32px", padding: 0, border: "none", borderRadius: "8px", cursor: "pointer" },
1747
1761
  onChange: (event) => setAccent(event.target.value)
1748
1762
  }),
@@ -1951,7 +1965,9 @@ window.__ModuleLoader__.load({
1951
1965
  let wallpaperBound;
1952
1966
  const syncWallpaper = () => {
1953
1967
  wallpaperRevision += 1;
1954
- wallpaperBound?.sync(wallpaperBackgroundCss(), readWallpaperOpacity(), readWallpaperBlur(), wallpaperRevision);
1968
+ // Store the raw data URL (not the CSS url(...) wrapper) so the
1969
+ // Wallpaper row can render an <img> preview and test `url !== null`.
1970
+ wallpaperBound?.sync(readWallpaper(), readWallpaperOpacity(), readWallpaperBlur(), wallpaperRevision);
1955
1971
  };
1956
1972
  applyWallpaper2(ctx);
1957
1973
  syncWallpaper();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-dream-skin",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
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",