@linxin666/dsh-client-ui-skin-center 0.4.4 → 0.4.5
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.i18n.yaml +2 -2
- package/README.md +67 -12
- package/README.zh.md +66 -11
- package/contracts/semantic-attrs-v1.md +20 -6
- package/lib/client.js +1764 -2950
- package/lib/client.js.map +1 -1
- package/lib/index.js +429 -6048
- package/package.json +1 -3
- package/skins/blue-fantasy/patches.css +28 -17
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 8c35732dd824eb7b137a9f4ef2c62e58eb7dbf65
|
|
6
|
+
README.zh.md: 23f6ce6952c7c42d47ca7109a3fcabc2a160be30
|
package/README.md
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
# Skin Center
|
|
1
|
+
# dsh-skins · Skin Center for DeepSeek Harness (DSH)
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="https://img.shields.io/npm/v/@linxin666/dsh-client-ui-skin-center?style=flat-square" alt="Version">
|
|
7
|
+
|
|
8
|
+
<img src="https://img.shields.io/badge/DSH-%3E%3D0.2.0--rc.2-4c6ef5?style=flat-square&labelColor=454a54" alt="DSH">
|
|
9
|
+
|
|
10
|
+
<img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<strong>Theme & Personalization Engine for DeepSeek Harness (DSH) Web GUI & Desktop Client</strong><br>
|
|
15
|
+
<em>Themes & Skins · Frosted Glass Blur · Custom Themes · Live Try-On · Wallpaper Engine via its dedicated plugin</em>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
5
18
|
`@linxin666/dsh-client-ui-skin-center` (cordis plugin id `ui-skin-center`) is the single skin package of the dsh Web GUI: it puts the skin list / try-on / apply into the real GUI as the first-level Skin Center settings section (settings → 皮肤中心, listing only installed skins), and it is the only loader and renderer for skins. A skin is a pure asset directory — no package.json, no npm publish, no cordis wiring — that couples only to the skin-center contract (`contracts/`); the skin center absorbs every official-DSH coupling behind that contract. The card carries its own enable switch (off disables try-on, apply and the background controls).
|
|
6
19
|
|
|
7
20
|
- List: shows "官方默认" (official default) plus every installed skin in the catalog with its name, tagline and accent color; the currently active target carries the Active marker. The catalog merges two sources: the default skin shipped inside this package (`skins/blue-fantasy/`) and user skins dropped into `$DSH_HOME/skins/<id>/` (a user skin with the same id shadows the built-in one). Every other skin of the collection is a market item: install it on demand from the DSH Market store (one-click install) into `$DSH_HOME/skins/<id>/`, where this same catalog manages it as a user skin — no restart, reopen the card or reload to pick it up. Skins whose `skin.json` fails validation are excluded fail-closed and reported as catalog diagnostics.
|
|
@@ -9,12 +22,22 @@ English | [中文](README.zh.md)
|
|
|
9
22
|
- Try-on / Apply: both go through the same atomic switch engine (`src/client/runtime/skin-controller.ts`). One switch is one new activation identity: fetch the scoped stylesheet, install it plus the background media and optional hooks, flip `html[data-dsh-skin="<id>"]`, then dispose the previous activation (append-only effect ledger, idempotent teardown). The latest request always wins; a failed or superseded switch leaves the previous skin fully intact. Try-on is the same switch without persistence — "Exit try-on" restores the committed skin. Apply persists the selection (`POST /api/skin-center/v2/active`). No page reload, no `cordis.patch.yml` rewrite, no boot-graph regeneration.
|
|
10
23
|
- First paint: the host half registers one index.html transform (`webServer.tapIndex`, single adapter module `src/tap-index-adapter.ts`) that stamps `html[data-dsh-skin]` and inserts the stylesheet links into every served document, so a reload boots straight into the active skin with no flash of the stock look. The tap fails closed to the stock look on any problem.
|
|
11
24
|
- Skin format (v2): `skin.json` (validated fail-closed, v1 fields `package`/`wiring`/`bodyAttr` ignored with migration warnings), `skin.css` (L1 token remaps + L2 semantic selectors), optional `patches.css` (L3 free selectors, high sensitivity), optional `hooks.mjs` (trusted escape hatch, high sensitivity), `assets/`, `preview/`. All CSS passes the safety pipeline (`src/core/css-safety/transform.ts`): every selector is force-scoped under `html[data-dsh-skin]`, `@import` / remote or protocol-relative URLs / escaping paths are hard errors. See `contracts/README.md`.
|
|
12
|
-
- Coverage contract: L1 remaps the official `--dsw-*` design tokens; L2 styles the semantic attributes (`data-dsh-surface` / `data-dsh-part` / `data-dsh-plugin`, enumeration in `contracts/semantic-attrs-v1.md`) which a compat adapter (`src/client/runtime/semantic-adapter.ts`) stamps onto the official shell DOM from stable anchors (`data-slot` outlets, `data-chat-flow-kind`, etc.); L3 patches carry any selector at the skin author's own risk. Plugins that output the semantic attributes themselves get the full L2 coverage; plugins that do not only get L1. A shared shell-rendering adapter applies only while a catalog skin
|
|
13
|
-
- Background priority: a
|
|
14
|
-
- Background controls: a background-occlusion slider (0–100%) veils the backdrop behind the panels for skins that paint one, two per-state Gaussian-blur sliders (0–20 px) control the backdrop for empty and populated conversations, an input-card blur slider (0–20 px) controls only the frosted area behind the composer, and a bubble-opacity slider (0–100%) drives translucent message bubbles for skins that expose bubble alpha.
|
|
15
|
-
- Wallpaper Engine bridge: the card can use the machine's local Wallpaper Engine library as the GUI backdrop. The host half (`src/we-library.ts` + `src/we-routes.ts`) locates the WE install (Steam app 431960: registry, every path in `libraryfolders.vdf`, durable `appmanifest_431960.acf` ownership, and probe paths on Windows), scans its projects and workshop content plus optional manual folders, and serves the inventory, media (Range-streamed), previews, web-wallpaper project files (with the WE API shim injected), and scene main-texture PNGs (decoded in-process from PKG/TEX by `src/pkg-extract.ts`, cached on disk) through same-origin `/api/skin-center/we/*` routes. Video wallpapers render in a `<video>`, web wallpapers in a sandboxed `<iframe>`, scene wallpapers live in the built-in WebGL player (2D layered scenes and 3D model scenes replayed with WE material/shader semantics); scene-embedded scripts are ignored while supported image, reflection, water and particle passes remain live, and a "static frame" render mode pins a zero-animation-cost image for any type. Per-wallpaper Import copies the project into `<harness-home>/skin-center/wallpapers/` so it survives Steam library changes, with update detection against the workshop original. Wallpapers are the user's own local files and are never uploaded or redistributed — Workshop content belongs to its authors. The Manual folders row accepts loose `.mp4`/`.webm` media, one project, a project collection, a Wallpaper Engine install root, or a Steam library root (`~` expands to the home directory).
|
|
25
|
+
- Coverage contract: L1 remaps the official `--dsw-*` design tokens; L2 styles the semantic attributes (`data-dsh-surface` / `data-dsh-part` / `data-dsh-plugin`, enumeration in `contracts/semantic-attrs-v1.md`) which a compat adapter (`src/client/runtime/semantic-adapter.ts`) stamps onto the official shell DOM from stable anchors (`data-slot` outlets, `data-chat-flow-kind`, etc.); L3 patches carry any selector at the skin author's own risk. Plugins that output the semantic attributes themselves get the full L2 coverage; plugins that do not only get L1. A shared shell-rendering adapter applies only while a catalog skin or a custom theme is active: it removes the workspace-list end fade, gives the composer placeholder an opaque theme-secondary text color, and reserves bottom clearance on conversation scrollports so messages remain readable above the sticky composer (#978), so individual skins do not need duplicate patches.
|
|
26
|
+
- Background priority: while a wallpaper renders, the skin and its background media stand down entirely (see "Wallpaper Engine"), so the wallpaper always has the backdrop to itself; otherwise the skin's manifest background media is the backdrop.
|
|
27
|
+
- Background controls: a background-occlusion slider (0–100%) veils the backdrop behind the panels for skins that paint one, two per-state Gaussian-blur sliders (0–20 px) control the backdrop for empty and populated conversations, an input-card blur slider (0–20 px) controls only the frosted area behind the composer, and a bubble-opacity slider (0–100%) drives translucent message bubbles for skins that expose bubble alpha. The active background blur uses a fixed `backdrop-filter` element behind the shell; 0 disables it entirely (no element, no GPU cost). The input-card frost rides its own body-level fixed follower (the `data-dsh-composer-frost` element) sized to the composer card, never the card itself: a `backdrop-filter` on the card would make it the containing block for the shell's fixed tooltips inside it and jolt the conversation on every hover.
|
|
16
28
|
- Legacy migration: on the first boot after the v2 upgrade, a one-shot bridge (`src/legacy-bridge.ts`) reads the retired `dsh-skin` managed section from the harness home `cordis.patch.yml` (where the v1 CLI wrote it; the active profile's `cordis.patch.yml` is probed as a secondary location), migrates the active skin id into the v2 selection store, and strips the legacy rows. The migration is idempotent and fails closed (the old state stays untouched on any error). It logs only when it migrated, cleaned, or failed — the nothing-to-migrate steady state stays silent (issue #788).
|
|
17
29
|
|
|
30
|
+
|
|
31
|
+
## Core Capabilities & Scenarios
|
|
32
|
+
|
|
33
|
+
| User Goal & Scenario | Stock DSH Web Limitation | Skin Center (dsh-skins) Solution |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| Personalized aesthetics and eye-care dark theme | Default single monochrome theme only | Bundled Blue Fantasy dark theme + one-click install for dozens of curated themes from Workshop |
|
|
36
|
+
| Interactive dynamic wallpaper via Wallpaper Engine | No dynamic video or animated wallpaper support | Delegated to the dedicated dsh-wallpaper-engine plugin (video, web, and 2D/3D WebGL real-time scenes), which this card installs from and hands the backdrop to |
|
|
37
|
+
| Frosted glass blur & composer scrim controls | Flat background with no visual depth or layering | Background scrim (0–100%), adaptive conversation blur, follower frosted composer glass & bubble opacity |
|
|
38
|
+
| Custom brand palette & CSS token remapping | Unable to tweak accent colors or contrast | Independent light/dark accent, background, foreground and contrast tuning with audited CSS token coverage |
|
|
39
|
+
| Live theme try-on and zero-flash hot switching | Theme changes require server restarts or reloads | Atomic hot-switch engine for live preview, clean rollback, and instant boot without white FOUC flashes |
|
|
40
|
+
|
|
18
41
|
## Most popular skins
|
|
19
42
|
|
|
20
43
|
The three most-liked skins in the Workshop's skin category on [dsh-market.com](https://dsh-market.com), in the site's default popularity order:
|
|
@@ -42,14 +65,43 @@ dsh plugin --profile web add @linxin666/dsh-client-ui-skin-center
|
|
|
42
65
|
|
|
43
66
|
skin-center is a self-contained bundle meeting the official DSH plugin standard (`dsh.bundle.patch` points to `cordis.patch.yml`); it can also be installed via git: `dsh plugin --profile web add github:<org>/dsh-web#<sha>` (the `prepare` script builds `lib/` in place). pnpm ≥10 requires authorizing `allowBuilds` before installing a git dependency; a local `link:` install has no such requirement.
|
|
44
67
|
|
|
68
|
+
## Wallpaper Engine
|
|
69
|
+
|
|
70
|
+
Wallpaper Engine support is **not bundled** here. It lives in its own plugin, [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine) (`dsh-plugin-wallpaper-engine`), which owns the wallpaper library, the video / web / scene rendering paths, the wallpaper settings surface and the glass over the wallpaper. It is the **recommended** Workshop item for wallpapers, and the skin center card installs it for you.
|
|
71
|
+
|
|
72
|
+
**One-click install**: open 设置 → 皮肤中心 and press **Install** on the card's wallpaper notice. The install goes through whichever plugin-management face the running host publishes — the official in-process plugin manager when it is there (the same call the official Plugins page makes, and the only writer on the packaged Desktop client), otherwise the family plugin-manager face. A host that publishes neither keeps the copy-command fallback.
|
|
73
|
+
|
|
74
|
+
By hand, the equivalent is:
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
dsh plugin --profile web add dsh-plugin-wallpaper-engine
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Restart the host afterwards (`dsh web`; DSH Desktop: fully quit the app and reopen it). The plugin adds its own settings page for choosing and tuning wallpapers.
|
|
81
|
+
|
|
82
|
+
### How the two share the page
|
|
83
|
+
|
|
84
|
+
The two plugins take turns rather than overlapping, and the handoff is automatic:
|
|
85
|
+
|
|
86
|
+
- **While a wallpaper renders**, the plugin stamps the stable `body[data-we-wallpaper]` attribute. The skin center reads that attribute and **stands its own visual work down**: no skin CSS, no skin background art, no hooks, no composer frost, and the `html[data-dsh-skin]` stamp comes off the page. Whatever you picked in the skin center is remembered but not painted — that plugin rewrites the same shell and paints its own glass, so anything else would fight it.
|
|
87
|
+
- **When the wallpaper stops**, the attribute clears and the remembered skin repaints on its own, with no reload and no re-applying.
|
|
88
|
+
- **When you ask for a skin yourself**, try-on and apply claim the stage once: the skin paints and `html[data-dsh-skin]` flips even while a wallpaper renders, because that stamp is the signal the plugin watches to hand the page back. Re-applying the skin you already wear counts as an action too, so the stamp is written on every apply rather than only when the selection changes. The claim is one-shot — if nothing answers within a short hand-back window, the skin stands down by itself and waits for the wallpaper to stop.
|
|
89
|
+
- **On the first screen, a remembered wallpaper wins before it renders.** That attribute is written by the wallpaper plugin's own client chain, hundreds of milliseconds after the document was delivered — too late for the browser's first paint, which the delivered document decides. So the host reads the wallpaper plugin's persisted selection (`$DSH_WE_DATA_DIR/config.json`, or `~/.dsh-wallpaper-engine/config.json`) while serving the page, and a wallpaper selected there keeps the skin out of that first screen entirely: no `html[data-dsh-skin]` stamp, no skin stylesheet. The withheld document is marked, so the GUI boot that follows it stands its first activation down too — the switch that would otherwise refill the gap a few hundred milliseconds later. The skin is still yours: if the wallpaper turns out not to render, your selection is applied as soon as the attribute is gone, or when that short window closes, whichever comes first.
|
|
90
|
+
|
|
91
|
+
The card says so while it is standing down, so a paused skin reads as a state, not as a bug. Whatever you picked is always persisted, and a skin the wallpaper never sees takes effect when the wallpaper stops. The skin center never writes the plugin state, and the plugin never writes the skin center state.
|
|
92
|
+
|
|
93
|
+
### Skins and wallpapers
|
|
94
|
+
|
|
95
|
+
Skin background art is part of a skin own look, so it is withheld together with the rest of the skin while a wallpaper renders. Skins that ship their own full-bleed plate (the ground-plate canvases in the catalog) additionally key their yield rules on `body[data-we-wallpaper]`, so they step aside rather than compete for the backdrop.
|
|
96
|
+
|
|
45
97
|
## Configuration
|
|
46
98
|
|
|
47
99
|
- **Enable switch**: turns the whole card (try-on / apply / background controls) on or off; persisted in the v2 active-state document.
|
|
48
100
|
- **Background sliders**: occlusion (0–100%), two backdrop blur radii, input-card blur (0–20 px), and bubble opacity (0–100%); persisted in the same v2 document.
|
|
49
101
|
- **Background persistence (remote-capable)**: background values live in the v2 active-state document (`$DSH_HOME/skin-center-active.json`, the `background` section) and are read/written through `GET|POST /api/skin-center/v2/active`, so paired remote desktops — where the settings surface is loopback-only — load and keep them across sessions. The `skin-background` section of the plugin's own configuration stays as the settings page's input face: a customized section is migrated into the v2 store once at boot, and later page edits are forwarded by the client. Card edits do not write back to that page, so it may show stale values until its next edit.
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **Where these settings live**: the
|
|
102
|
+
- **Custom theme**: light/dark accent, background, foreground and contrast profiles plus the applied marker; persisted as a versioned contract in the `skin-custom-theme` section of the plugin's own configuration.
|
|
103
|
+
- **Wallpaper settings**: not part of this configuration. They belong to `dsh-plugin-wallpaper-engine`, which serves its own settings page; a retired `skin-wallpaper` section left in an older profile is ignored and never rewritten.
|
|
104
|
+
- **Where these settings live**: the two sections are one plugin configuration — the profile entry's own `Config`. The Host derives that entry's settings page from the schema in the GUI, and the card writes the same values; there is no separate settings document.
|
|
53
105
|
- **User skin directory**: `$DSH_HOME/skins/<id>/`; override precedence is `DSH_SKINS_HOME`, then `DSH_SKINS_DIR`, then `$DSH_HOME/skins`.
|
|
54
106
|
|
|
55
107
|
## Security model
|
|
@@ -63,7 +115,7 @@ skin-center is a self-contained bundle meeting the official DSH plugin standard
|
|
|
63
115
|
|
|
64
116
|
- Inline styles written by plugins at runtime can only be overridden by L3 `!important` patches.
|
|
65
117
|
- Plugins that do not output semantic attributes (and have no stable DOM anchors) receive L1 token coverage only.
|
|
66
|
-
-
|
|
118
|
+
- Wallpaper pause-on-hidden, wallpaper blur, dimming and sound live in `dsh-plugin-wallpaper-engine`'s own settings; the skin center has no wallpaper controls and its card only reports the plugin's state.
|
|
67
119
|
|
|
68
120
|
## Telemetry
|
|
69
121
|
|
|
@@ -84,12 +136,14 @@ skins/skin-center/
|
|
|
84
136
|
src/active-state.ts # active-skin selection persistence
|
|
85
137
|
src/legacy-bridge.ts # one-shot v1 → v2 migration
|
|
86
138
|
src/http-utils.ts / harness-home.ts # shared route helpers / DSH path resolution
|
|
87
|
-
src/we-library.ts / we-routes.ts / we-shim-source.ts / pkg-extract.ts # Wallpaper Engine bridge
|
|
88
139
|
src/client/runtime/ # effect ledger, decoration layers, semantic adapter, switch controller, boot store
|
|
89
140
|
src/client/SkinCenter.tsx # the settings card
|
|
90
141
|
src/core/custom-theme.ts # versioned palette contract + audited token-only CSS generator
|
|
91
142
|
src/client/custom-theme-controller.ts / CustomThemePanel.tsx # persistence/runtime owner + editor card
|
|
92
|
-
src/client/background.ts
|
|
143
|
+
src/client/background.ts # scrim + blur controls
|
|
144
|
+
src/external-wallpaper.ts # read-only probe of the delegated wallpaper plugin
|
|
145
|
+
src/client/runtime/external-wallpaper-engine.ts # stands skins down while that plugin renders
|
|
146
|
+
src/client/external-wallpaper-install.ts # one-click install through the host's plugin-management face
|
|
93
147
|
skins/<id>/ # built-in skins (pure asset directories)
|
|
94
148
|
```
|
|
95
149
|
|
|
@@ -100,4 +154,5 @@ skins/skin-center/
|
|
|
100
154
|
- [x] Try-on takes effect immediately and Exit restores the committed skin; only one skin is ever on the page
|
|
101
155
|
- [x] One-click apply switches atomically with no reload; a later page load boots straight into the skin (no FOUC)
|
|
102
156
|
- [x] The custom theme keeps independent light/dark profiles, survives reload, and never overrides an active catalog skin
|
|
103
|
-
- [x]
|
|
157
|
+
- [x] Background scrim and blur controls are unaffected by skin switches
|
|
158
|
+
- [x] While the delegated wallpaper plugin renders, no skin, glass or background art from this plugin is on the page, and the remembered skin returns when it stops
|
package/README.zh.md
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-skins · DeepSeek Harness (DSH) 皮肤中心
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="https://img.shields.io/npm/v/@linxin666/dsh-client-ui-skin-center?style=flat-square" alt="Version">
|
|
7
|
+
|
|
8
|
+
<img src="https://img.shields.io/badge/DSH-%3E%3D0.2.0--rc.2-4c6ef5?style=flat-square&labelColor=454a54" alt="DSH">
|
|
9
|
+
|
|
10
|
+
<img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<strong>DeepSeek Harness(DSH)官方 Web GUI 与桌面客户端专属主题与个性化美化引擎</strong><br>
|
|
15
|
+
<em>主题换肤 · 毛玻璃高斯模糊 · 自定义深浅色配色 · 创意工坊即时试穿 · Wallpaper Engine 由专用插件提供</em>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
5
18
|
`@linxin666/dsh-client-ui-skin-center`(cordis 插件 id `ui-skin-center`)是 dsh Web GUI 唯一的皮肤包:它把皮肤列表 / 试穿 / 应用做成一级设置分区「皮肤中心」(设置 → 皮肤中心,只列已安装皮肤),并且是所有皮肤的唯一加载器与渲染器。皮肤是纯资产目录——没有 package.json、不发 npm、不接 cordis 接线——只与皮肤中心契约(`contracts/`)耦合;皮肤中心把对官方 DSH 的全部耦合吸收在契约之后。卡片自带总开关(关闭即停用试穿、应用与背景控制)。
|
|
6
19
|
|
|
7
20
|
- 列表:展示「官方默认」加目录册里已安装的皮肤(名称、标语、强调色),当前应用目标带「使用中」标记。目录册合并两个来源:随本包内置的默认皮肤(`skins/blue-fantasy/`)与放进 `$DSH_HOME/skins/<id>/` 的用户皮肤(同 id 时用户皮肤遮蔽内置皮肤)。皮肤集中的其余皮肤都是市场条目:在 DSH 市场商店一键按需安装到 `$DSH_HOME/skins/<id>/`,即由同一目录册作为用户皮肤管理——无需重启,重开卡片或刷新页面即收录。`skin.json` 校验失败的皮肤按 fail-closed 排除,并作为目录诊断上报。
|
|
@@ -9,12 +22,22 @@
|
|
|
9
22
|
- 试穿 / 应用:两者走同一个原子切换引擎(`src/client/runtime/skin-controller.ts`)。一次切换 = 一个新的 activation identity:取回已限定作用域的样式表,安装样式、背景媒体与可选 hooks,翻转 `html[data-dsh-skin="<id>"]`,然后销毁上一个 activation(append-only 效果账本,幂等清理)。最新请求永远胜出;失败或被淘汰的切换完整保留旧皮肤。试穿是同一个切换但不落盘——「退出试穿」恢复已提交的皮肤。应用会持久化选择(`POST /api/skin-center/v2/active`)。不刷新页面、不改写 `cordis.patch.yml`、不重建启动图。
|
|
10
23
|
- 首屏:host 半区注册一个 index.html 转换(`webServer.tapIndex`,单一适配模块 `src/tap-index-adapter.ts`),向每份送达的文档盖 `html[data-dsh-skin]` 属性并插入样式表链接,刷新后直接以当前皮肤启动,无官方原貌闪屏。tap 出任何问题都 fail-closed 回官方原貌。
|
|
11
24
|
- 皮肤格式(v2):`skin.json`(fail-closed 校验,v1 字段 `package`/`wiring`/`bodyAttr` 忽略并给迁移警告)、`skin.css`(L1 token 重映射 + L2 语义选择器)、可选 `patches.css`(L3 自由选择器,高敏感)、可选 `hooks.mjs`(受信逃逸舱,高敏感)、`assets/`、`preview/`。所有 CSS 经过安全管线(`src/core/css-safety/transform.ts`):每个选择器强制限定在 `html[data-dsh-skin]` 下,`@import` / 远程或协议相对 URL / 越界路径直接报错。见 `contracts/README.md`。
|
|
12
|
-
- 覆盖契约:L1 重映射官方 `--dsw-*` 设计 token;L2 样式语义属性(`data-dsh-surface` / `data-dsh-part` / `data-dsh-plugin`,枚举见 `contracts/semantic-attrs-v1.md`),由兼容适配器(`src/client/runtime/semantic-adapter.ts`)从稳定锚点(`data-slot` 出口、`data-chat-flow-kind` 等)为官方壳层 DOM 打标;L3 补丁任意选择器,脆弱性由皮肤作者自负。主动输出语义属性的插件获得完整 L2 覆盖;不输出的只享受 L1
|
|
13
|
-
-
|
|
25
|
+
- 覆盖契约:L1 重映射官方 `--dsw-*` 设计 token;L2 样式语义属性(`data-dsh-surface` / `data-dsh-part` / `data-dsh-plugin`,枚举见 `contracts/semantic-attrs-v1.md`),由兼容适配器(`src/client/runtime/semantic-adapter.ts`)从稳定锚点(`data-slot` 出口、`data-chat-flow-kind` 等)为官方壳层 DOM 打标;L3 补丁任意选择器,脆弱性由皮肤作者自负。主动输出语义属性的插件获得完整 L2 覆盖;不输出的只享受 L1。目录皮肤或自定义主题激活期间还会启用公共壳层渲染适配器:它清除工作区列表末端 fade,将 composer 占位符固定为不透明的主题次级文本色,并为会话滚动口保留底部安全间距以保证吸底正文不被输入区覆盖(#978),各皮肤无需重复补丁。
|
|
26
|
+
- 背景优先级:壁纸渲染期间皮肤及其背景媒体整体停画(见「Wallpaper Engine」),背景完全归壁纸;否则皮肤清单背景媒体即背景。
|
|
14
27
|
- 背景控制:背景遮蔽滑杆(0–100%)为画背景的皮肤在面板后加纱,两个按状态的高斯模糊滑杆(0–20 px)分别控制空对话与有内容时的背景,输入卡模糊滑杆(0–20 px)只控制输入卡背后的磨砂区域,气泡不透明度滑杆(0–100%)控制支持气泡 alpha 的皮肤消息气泡。整张壁纸模糊仍是独立的壁纸设置。背景模糊通过外壳之后的固定 `backdrop-filter` 元素施加;0 完全关闭(无元素、无 GPU 开销)。输入卡磨砂由独立的 body 级固定跟随层(`data-dsh-composer-frost` 元素)承担并按输入卡尺寸跟随,**不**挂在卡片本体上:卡片一旦带 `backdrop-filter` 就会成为其中 shell fixed tooltip 的包含块,悬停时整页会话会被顶动。
|
|
15
|
-
- Wallpaper Engine 桥:卡片可把本机 Wallpaper Engine 库用作 GUI 背景。host 半区(`src/we-library.ts` + `src/we-routes.ts`)定位 WE 安装(Steam 应用 431960:Windows 注册表、`libraryfolders.vdf` 中的全部库路径、持久的 `appmanifest_431960.acf` 所有权事实与探测路径),扫描项目与创意工坊内容及可选手动文件夹,经同源 `/api/skin-center/we/*` 路由提供清单、媒体(Range 流式)、预览图、web 壁纸项目文件(注入 WE API shim)与场景壁纸主贴图 PNG(由 `src/pkg-extract.ts` 进程内解码 PKG/TEX,磁盘缓存)。视频壁纸用 `<video>` 渲染,web 壁纸用沙箱 `<iframe>`,场景壁纸经内置 WebGL 播放器实时渲染(2D 图层场景与 3D 模型场景按 WE 材质/着色器语义回放);场景内嵌脚本会被忽略,但受支持的图像、反射、水面与粒子通道仍保持实时渲染,「静态帧」模式可为任意类型钉一张零动画开销的图。单张壁纸的导入会把项目复制进 `<harness-home>/skin-center/wallpapers/`,脱离 Steam 库变更也能用,并检测创意工坊原作更新。壁纸都是用户本机文件,从不上传或再分发——创意工坊内容归原作者。「手动文件夹」行可接收零散 `.mp4`/`.webm` 媒体、单个项目、项目合集、Wallpaper Engine 安装根目录或 Steam 库根目录(`~` 展开为主目录)。
|
|
16
28
|
- 旧版迁移:v2 升级后的首次启动,一次性桥(`src/legacy-bridge.ts`)读取 harness home 根 `cordis.patch.yml`(v1 CLI 写入处;活动 profile 的 `cordis.patch.yml` 作为次级位置也会探测)里已退役的 `dsh-skin` 受管段,把活动皮肤 id 迁进 v2 选择存储,并清除旧行。迁移幂等且 fail-closed(出错时旧状态原样保留)。仅在发生迁移、清理或失败时输出日志,无 legacy 状态的稳态保持静默(issue #788)。
|
|
17
29
|
|
|
30
|
+
|
|
31
|
+
## 核心特性与场景
|
|
32
|
+
|
|
33
|
+
| 核心使用场景 | 原生 DSH Web 局限 | 皮肤中心(dsh-skins)解决方案 |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| 个性化界面视觉与护眼暗色模式 | 仅支持单一官方默认黑白主题 | 内置经典 Blue Fantasy 蓝色幻想暗色主题,支持从创意工坊一键安装数十款精美主题 |
|
|
36
|
+
| Wallpaper Engine 动态壁纸交互背景 | 无法使用动态壁纸或视频背景 | 交给专用的 dsh-wallpaper-engine 插件(视频、Web 与 2D/3D WebGL 实时场景壁纸),本卡片负责安装指引并把背景让给它 |
|
|
37
|
+
| 毛玻璃背景模糊与输入卡磨砂控制 | 界面背景单一,无视觉层次感 | 提供全局背景遮罩(0–100%)、空会话/有内容动态高斯模糊、输入框局部磨砂跟随与气泡透明度滑杆 |
|
|
38
|
+
| 自定义品牌与个性配色重映射 | 无法自定义主题颜色与对比度 | 独立编辑浅色/深色强调色、背景色、前景色与对比度,自动生成审计级 CSS token 覆盖层 |
|
|
39
|
+
| 主题资产即时试穿与无感热切换 | 更换主题需重启服务或刷新页面 | 原子切换引擎实现一键即时试穿、退出恢复与持久化应用,刷新直接以当前皮肤启动零白屏闪烁 |
|
|
40
|
+
|
|
18
41
|
## 人气皮肤
|
|
19
42
|
|
|
20
43
|
[dsh-market.com](https://dsh-market.com) 创意工坊皮肤分类里人气最高的三款皮肤,按网站默认的「按人气」排序:
|
|
@@ -42,14 +65,43 @@ dsh plugin --profile web add @linxin666/dsh-client-ui-skin-center
|
|
|
42
65
|
|
|
43
66
|
皮肤中心是符合官方 DSH 插件标准的自包含 bundle(`dsh.bundle.patch` 指向 `cordis.patch.yml`);也可经 git 安装:`dsh plugin --profile web add github:<org>/dsh-web#<sha>`(`prepare` 脚本就地构建 `lib/`)。pnpm ≥10 安装 git 依赖前需授权 `allowBuilds`;本地 `link:` 安装无此要求。
|
|
44
67
|
|
|
68
|
+
## Wallpaper Engine
|
|
69
|
+
|
|
70
|
+
Wallpaper Engine 支持**不再内置**在本包。它由独立插件 [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine)(`dsh-plugin-wallpaper-engine`)提供,壁纸库、视频 / 网页 / 场景三条渲染路径、壁纸设置面与壁纸之上的玻璃都归它管。它是壁纸方面的**推荐**工坊条目,皮肤中心卡片可直接帮你装上。
|
|
71
|
+
|
|
72
|
+
**一键安装**:打开 设置 → 皮肤中心,在卡片的壁纸提示条上点「一键安装」。安装走宿主当前发布的插件管理面——存在官方进程内插件管理器时优先用它(与官方插件页同一个调用,也是打包版桌面客户端上唯一的写入者),否则退回家族插件管理器面;两者都没有时保留复制命令的兜底。
|
|
73
|
+
|
|
74
|
+
手工等价命令:
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
dsh plugin --profile web add dsh-plugin-wallpaper-engine
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
装完重启宿主(`dsh web`;DSH Desktop 需完全退出应用后重新打开)。该插件自带设置页用于选择与调节壁纸。
|
|
81
|
+
|
|
82
|
+
### 两者如何共处一页
|
|
83
|
+
|
|
84
|
+
两个插件轮流上阵而不是互相覆盖,切换是自动的:
|
|
85
|
+
|
|
86
|
+
- **壁纸渲染期间**,该插件给 `body` 打上稳定属性 `data-we-wallpaper`。皮肤中心读取该属性并**整体停掉自己的视觉工作**:不加载皮肤 CSS、不画皮肤背景图、不跑 hooks、不挂输入卡磨砂,并把 `html[data-dsh-skin]` 属性从页面上撤下。你在皮肤中心选的皮肤会被记住但不绘制——该插件改写了同一个壳层并画自己的玻璃,其他东西只会与它相争。
|
|
87
|
+
- **壁纸停止时**,属性清除,被记住的皮肤自动重新上妆,无需刷新、无需重新应用。
|
|
88
|
+
- **当你主动试穿或应用皮肤时**,这一次激活会先「抢一次台」:即使壁纸仍在渲染,皮肤也会上妆并翻上 `html[data-dsh-skin]`——该插件正是盯这个属性把舞台让回来的。对已穿戴的同一款再点一次「应用」同样算一次动作,因此每次应用都会写这个属性,而不是只在选择变化时才写。这个让路信号只发一次:若让路窗口内始终没有回应,皮肤会自行退回停画,等壁纸停止后再按记忆恢复。
|
|
89
|
+
- **首屏在被渲染之前,就先认下已记住的壁纸。** 上面那个属性是壁纸插件的客户端链在文档送达之后数百毫秒才写上的,而浏览器的首帧由送达的文档决定,等它到达时已经晚了。因此宿主在出页面时会同步读壁纸插件的持久化选择(`$DSH_WE_DATA_DIR/config.json`,缺省 `~/.dsh-wallpaper-engine/config.json`),里面选着壁纸时这一屏就完全不注入皮肤:不盖 `html[data-dsh-skin]`、不插皮肤样式表。被撤下的文档还会打一个标记,因此随后启动的界面也会先按住它的第一次激活——否则几百毫秒后那一次切换就会把这个空档重新填上。于是既有皮肤又有壁纸的页面刷新后直接开在壁纸上,没有一闪而过的皮肤要撤掉。皮肤仍然归你:若壁纸最终没能渲染,属性一撤掉、或这扇短窗关上(以先到者为准),运行时就会照旧把记住的皮肤应用回来。
|
|
90
|
+
|
|
91
|
+
停画期间卡片会写明原因,因此「皮肤不见了」读起来是一个状态而不是故障。你选中的皮肤任何时候都会落盘,壁纸没让它上场的部分也会在壁纸停止后自动生效。皮肤中心从不写该插件的状态,该插件也从不写皮肤中心的状态。
|
|
92
|
+
|
|
93
|
+
### 皮肤与壁纸
|
|
94
|
+
|
|
95
|
+
皮肤背景图属于皮肤自身外观的一部分,因此壁纸渲染期间会随皮肤整体停画。自带满幅底板的皮肤(目录里的 ground-plate 画布类)另把让路规则锚定在 `body[data-we-wallpaper]` 上,从而主动让位而不是争夺背景。
|
|
96
|
+
|
|
45
97
|
## 配置
|
|
46
98
|
|
|
47
99
|
- **总开关**:开关整张卡片(试穿 / 应用 / 背景控制);持久化在 v2 活跃状态文档中。
|
|
48
100
|
- **背景滑杆**:遮蔽(0–100%)、两个背景模糊半径、输入卡模糊(0–20 px)与气泡不透明度(0–100%),持久化在同一 v2 文档中。
|
|
49
101
|
- **背景持久化(支持远程)**:背景设置存放在 v2 活跃状态文档(`$DSH_HOME/skin-center-active.json` 的 `background` 段),经 `GET|POST /api/skin-center/v2/active` 读写,因此已配对的远程桌面(settings 通道仅限本机回环)也能读取并跨会话保存。插件自身配置中的 `skin-background` 段保留为设置页的输入面:已定制的配置在启动时一次性迁移进 v2 存储,之后的设置页修改由客户端转发。卡片内的修改不回写该设置页,因此它可能显示旧值,直到下一次从设置页修改。
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
102
|
+
- **自定义主题**:浅色/深色的强调色、背景色、前景色、对比度配置及应用标记,以版本化契约持久化在插件自身配置的 `skin-custom-theme` 段。
|
|
103
|
+
- **壁纸设置**:不属于本配置。它们归 `dsh-plugin-wallpaper-engine`,由该插件提供自己的设置页;旧 profile 里遗留的 `skin-wallpaper` 段会被忽略,且不会被改写。
|
|
104
|
+
- **这些设置放在哪里**:以上两段同属一份插件配置——该 profile 条目自己的 `Config`。宿主据此 schema 在 GUI 中生成该条目的设置页,卡片写入的是同一批值;不存在单独的 settings 文档。
|
|
53
105
|
- **用户皮肤目录**:`$DSH_HOME/skins/<id>/`;覆盖优先级为 `DSH_SKINS_HOME`、`DSH_SKINS_DIR`、`$DSH_HOME/skins`。
|
|
54
106
|
|
|
55
107
|
## 安全模型
|
|
@@ -63,7 +115,7 @@ dsh plugin --profile web add @linxin666/dsh-client-ui-skin-center
|
|
|
63
115
|
|
|
64
116
|
- 插件运行时写入的内联样式只能经 L3 `!important` 补丁覆盖。
|
|
65
117
|
- 不输出语义属性(且无稳定 DOM 锚点)的插件只享受 L1 token 覆盖。
|
|
66
|
-
-
|
|
118
|
+
- 壁纸的「隐藏时暂停」、模糊、压暗与声音都在 `dsh-plugin-wallpaper-engine` 自己的设置里;皮肤中心没有任何壁纸控件,卡片只报告该插件的状态。
|
|
67
119
|
|
|
68
120
|
## 数据遥测
|
|
69
121
|
|
|
@@ -84,12 +136,14 @@ skins/skin-center/
|
|
|
84
136
|
src/active-state.ts # 活动皮肤选择持久化
|
|
85
137
|
src/legacy-bridge.ts # 一次性 v1 → v2 迁移
|
|
86
138
|
src/http-utils.ts / harness-home.ts # 路由共享助手 / DSH 路径解析
|
|
87
|
-
src/we-library.ts / we-routes.ts / we-shim-source.ts / pkg-extract.ts # Wallpaper Engine 桥
|
|
88
139
|
src/client/runtime/ # 效果账本、装饰层、语义适配器、切换控制器、启动存储
|
|
89
140
|
src/client/SkinCenter.tsx # 设置卡片
|
|
90
141
|
src/core/custom-theme.ts # 版本化配色契约 + 经审计的纯 token CSS 生成器
|
|
91
142
|
src/client/custom-theme-controller.ts / CustomThemePanel.tsx # 持久化/运行时控制器 + 编辑卡片
|
|
92
|
-
src/client/background.ts
|
|
143
|
+
src/client/background.ts # 遮罩 + 模糊控制
|
|
144
|
+
src/external-wallpaper.ts # 只读探测独立壁纸插件
|
|
145
|
+
src/client/runtime/external-wallpaper-engine.ts # 该插件渲染期间停画皮肤
|
|
146
|
+
src/client/external-wallpaper-install.ts # 经宿主插件管理面一键安装
|
|
93
147
|
skins/<id>/ # 内置皮肤(纯资产目录)
|
|
94
148
|
```
|
|
95
149
|
|
|
@@ -100,4 +154,5 @@ skins/skin-center/
|
|
|
100
154
|
- [x] 试穿即时生效,退出完整恢复已提交皮肤;页面上永远只有一套皮肤
|
|
101
155
|
- [x] 一键应用原子切换、无需刷新;后续页面加载直接以该皮肤启动(无 FOUC)
|
|
102
156
|
- [x] 自定义主题保留独立浅色/深色配置、刷新后恢复,且不会覆盖已激活的目录册皮肤
|
|
103
|
-
- [x]
|
|
157
|
+
- [x] 背景遮罩与模糊控制不受换肤影响
|
|
158
|
+
- [x] 独立壁纸插件渲染期间,本插件不留下任何皮肤、玻璃或背景图;它停止后被记住的皮肤自动恢复
|
|
@@ -36,15 +36,23 @@
|
|
|
36
36
|
### 背景自有标记(owner: skin-center)
|
|
37
37
|
|
|
38
38
|
皮肤中心「有背景艺术可见」期间的自有标记;均为 body/html 级属性(按上文纪律
|
|
39
|
-
|
|
39
|
+
另行管理):
|
|
40
40
|
|
|
41
41
|
| 属性 | 位置 | 含义 / 锚定方式 |
|
|
42
42
|
| --- | --- | --- |
|
|
43
|
-
| `data-dsh-
|
|
43
|
+
| `data-dsh-skin` | html(html 级,owner: skin-center) | 当前皮肤 id:皮肤 CSS 强制作用域于此,目录内皮肤的自有让路规则另锚定 `body[data-we-wallpaper]`。它是**皮肤在画**与**皮肤要求上台**两义的公开信号——独立壁纸插件据此反向让路。用户显式发起的激活(试穿 / 应用,含对同一款的重复应用)这一次照常上妆并翻上该属性,随后停画判定在下一帧自然成立;无人应答时在一个让路窗口(`USER_INITIATED_YIELD_GRACE_MS`)后自行退回停画(#49) |
|
|
44
|
+
| `data-dsh-backdrop-active` | html + body(body/html 级,另行管理) | 皮肤背景媒体(`backgroundMedia`)挂载期间置 `true`(`backdrop-scene.ts`),卸载 / 禁用清净;供 composer seat 遮罩统一中和与输入区前置磨砂面板规则锚定(#777) |
|
|
44
45
|
| `data-dsh-conversation-content` | html + body(body/html 级,另行管理) | 当前对话存在消息行(`[data-chat-anchor-key]`)期间置 `true`;`backdrop-scene.ts` 在背景可见时随 MutationObserver 更新。输入卡磨砂仅在 backdrop-active 且本标记置位时启用,空对话不显示多余模糊(#777 follow-up) |
|
|
45
|
-
| `data-dsh-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
| `data-dsh-composer-frost` | body 级空元素(元素级,owner: skin-center) | 皮肤中心在 backdrop-active 且 conversation-content 置位期间挂载的输入卡磨砂层:body 级 fixed 兄弟元素,按输入卡 border box 跟随(rAF 合并测量),仅承载 `backdrop-filter`;标记清除即移除。磨砂**不能**挂在输入卡上——非 none 的 `backdrop-filter` 会让卡片成为其 fixed 后代的包含块,把官方 tooltip 推进会话滚动口并撑高 `scrollHeight`(#1724)。壁纸插件渲染期间本层不挂载(见下) |
|
|
47
|
+
|
|
48
|
+
### 外部壁纸标记(owner: dsh-plugin-wallpaper-engine,只读消费)
|
|
49
|
+
|
|
50
|
+
壁纸由独立插件 `dsh-plugin-wallpaper-engine` 提供,皮肤中心不再自带 WE 桥
|
|
51
|
+
(#39)。该插件在渲染壁纸期间给 `body` 打上自有属性,皮肤中心只读它、从不写:
|
|
52
|
+
|
|
53
|
+
| 属性 | 位置 | 含义 / 锚定方式 |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| `data-we-wallpaper` | body(元素级,owner: 外部壁纸插件) | 外部插件渲染壁纸期间置位,停止时移除。皮肤中心在置位期间**整体停画皮肤**(不加载皮肤 CSS、不画 `backgroundMedia`、不跑 hooks、不挂 composer 磨砂,并把 `html[data-dsh-skin]` 属性撤下),用户选择保留,属性清除即自动恢复;用户显式发起的激活是唯一例外,它先翻 `html[data-dsh-skin]` 抢一次台以驱动对方让路,无人应答则在一个让路窗口后自行退回停画(#49);皮肤目录内的让路规则(`body[data-we-wallpaper]::after` 等)也锚定它。等价属主与写者只有外部插件一方 |
|
|
48
56
|
|
|
49
57
|
## part 组(81 行,含各 owner 行)
|
|
50
58
|
|
|
@@ -69,7 +77,13 @@ family / 插件区域:
|
|
|
69
77
|
| `sidebar-entry` | shell(行盒)+ 注册插件(身份) | 插件经 `sidebar.panellist` 注册的侧栏面板行(任务看板 / ssh / 技能中心;官方 Plugins / Schedule 行不属此值)。行盒归 shell,兼容适配器按 `[class*="panelRow"]:has([data-dsh-panel-entry])` 补打——CSS-module 后缀 + 插件字形身份,同 `new-session` 手法;上游诉求见下文脆弱点 2 |
|
|
70
78
|
| `header` | task-board | 看板头;`[data-dsh-taskboard-board] > header` |
|
|
71
79
|
| `column` | task-board | 状态列;`section[data-status]` |
|
|
72
|
-
| `card` | task-board | 任务卡;列内 `[data-status]`
|
|
80
|
+
| `card` | task-board | 任务卡;列内 `article[data-status]` 条目,`data-tone` 为最近执行结果(running / succeeded / failed / cancelled,无执行或归档时缺省),`data-compact` 标记紧凑密度 |
|
|
81
|
+
| `card-open` | task-board | 铺满卡片的透明打开按钮(键盘与读屏入口);`article[data-dsh-part="card"] > button[data-dsh-part="card-open"]` |
|
|
82
|
+
| `card-title` / `card-kind` / `card-excerpt` / `card-time` / `card-run` | task-board | 卡片标题、标题类型徽章(`[Bug]:` 前缀)、描述摘要、按列选择的时间标签、最近执行结果与次数;均在 `[data-dsh-part="card"]` 内 |
|
|
83
|
+
| `card-session` | task-board | 卡片上打开最近执行会话的快捷按钮 |
|
|
84
|
+
| `card-group` / `card-group-toggle` | task-board | 已结算列的时间分组(`data-group` 为 today / week / earlier)与折叠开关 |
|
|
85
|
+
| `density-toggle` | task-board | 列头的紧凑/完整卡片切换;`aria-pressed` 表示紧凑 |
|
|
86
|
+
| `github-badge` | task-board-github | 卡片 meta 行内的 Issue 编号徽章;URL 为 http(s) 时是新标签打开的 `a`,否则为 `span` |
|
|
73
87
|
| `detail` | task-board | 任务详情面板 |
|
|
74
88
|
| `tag-filter` | task-board | 标签筛选条;`[data-dsh-taskboard-board] [data-dsh-part="tag-filter"]` |
|
|
75
89
|
| `tag-chip` | task-board | 筛选条内的标签胶囊;`[data-dsh-part="tag-chip"]`,`data-tag-tone` 为 0-5 调色板槽 |
|