dsh-mpkg-wallpaper 3.1.0 → 3.1.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.en.md CHANGED
@@ -16,7 +16,7 @@ One plugin covers the whole wallpaper chain — import, parsing, playback, rotat
16
16
  - **Video files**: pick an mp4/webm file directly as a video background
17
17
 
18
18
  **🌊 Full-screen frosted blur suite**
19
- - **Unified blur (own section)**: one slider controls the wallpaper blur degree of the whole screen (0 = sharp, higher = more blurred); sidebar/title-bar fog thickness, chat-area follow and new-chat button follow are adjustable independently; when on it takes over the items below (sidebar frost, title-bar frost and the frosted-blur slider are disabled with a hint)
19
+ - **Unified blur (own section)**: one slider controls the wallpaper blur degree of the whole screen (0 = sharp, higher = more blurred); sidebar fog thickness, chat-area follow and new-chat button follow are adjustable independently; when on it takes over the sidebar frost and the frosted-blur slider (the title bar is NOT taken over - it follows its own frost slider, transparent by default)
20
20
  - **UI blur (own section)**:
21
21
  - **Blur dialogs**: generic center-screen windows + the chat input box (frosted backdrop; text scrolling under the input box turns hazy)
22
22
  - **Blur settings panel**: the DSH settings panel with its own toggle + amount
@@ -51,7 +51,7 @@ One plugin covers the whole wallpaper chain — import, parsing, playback, rotat
51
51
 
52
52
  - **Background source**: master toggle, hybrid large-file mode, .mpkg file, image URL, local image/GIF, local wallpaper library (Steam discovery + custom folder + folder picker), wallpaper switching & rotation
53
53
  - **Appearance**: panel opacity, frosted blur, lens zoom, lens position
54
- - **Unified blur**: full-screen blur toggle + amount, sidebar/title-bar fog thickness, chat-area follow, new-chat button follow
54
+ - **Unified blur**: full-screen blur toggle + amount, sidebar fog thickness, chat-area follow, new-chat button follow
55
55
  - **UI blur**: dialog / settings panel / download-confirm popup blur (each with its own toggle + amount), popover blur, mask blur, sidebar frost (Aqua scheme), Deep diving background box, title-bar frost/show (independent frost amount)
56
56
  - **Other**: sidebar shows wallpaper, light sharpen, third-party UI radius compat (off by default), update check / one-click hot update, restore defaults
57
57
 
@@ -106,7 +106,7 @@ Settings → **Wallpaper Engine Background**:
106
106
  | Image URL / local image | Plain images or GIFs |
107
107
  | Panel opacity | 50–100% |
108
108
  | Frosted blur | How blurred the wallpaper itself is, 0–40px (0 = sharp) |
109
- | Unified blur (own section) | One slider controls the whole screen's wallpaper blur degree (0=sharp, higher=more blurred); sidebar/title-bar fog thickness, chat-area follow and new-chat follow adjustable; takes over the items below when on |
109
+ | Unified blur (own section) | One slider controls the whole screen's wallpaper blur degree (0=sharp, higher=more blurred); sidebar fog thickness, chat-area follow and new-chat follow adjustable; takes over sidebar frost and the frosted-blur slider when on (title bar keeps its own frost slider) |
110
110
  | Dialog / settings panel / confirm popup / popover / mask blur | Each with its own toggle + amount slider; sidebar frost (Aqua scheme, auto-lifted while a dialog is open) |
111
111
  | Lens zoom / position | Zoom (10–2000%) and pan the background; zoom out to see components at the picture edges |
112
112
  | Sidebar / title-bar wallpaper | Toggles; off = solid opaque color for that area; title-bar frost amount adjustable independently |
@@ -117,49 +117,48 @@ Settings → **Wallpaper Engine Background**:
117
117
 
118
118
  ## Install
119
119
 
120
- ### Option 1: dsh plugin add (recommended)
120
+ The plugin is published on npm (`dsh-mpkg-wallpaper`). Pick one:
121
+
122
+ ### Option 1: dsh plugin add (recommended, market-recognized)
121
123
 
122
124
  ```bash
123
125
  dsh plugin --profile web add dsh-mpkg-wallpaper
124
126
  # restart dsh web, then hard-refresh the browser (Ctrl+F5)
125
127
  ```
126
128
 
127
- ### Option 2: pnpm install (standard for the pnpm-workspace profile)
128
-
129
- ```bash
130
- # 1. Put the plugin folder under the profile's node_modules (or extract the GitHub zip)
131
- git clone https://github.com/XHR666/dsh-mpkg-wallpaper.git $DSH_HOME/profiles/web/node_modules/dsh-mpkg-wallpaper
132
- # (if your profile is not at ~/.dsh/profiles/web, use your profile directory)
129
+ Installs from the official npm registry and writes into the profile's `package.json`
130
+ dependencies — the plugin market recognizes it as installed, shows the download count,
131
+ and can manage updates.
133
132
 
134
- # 2. Register a line in the profile's cordis.patch.yml:
135
- # - insert:
136
- # - id: dsh-mpkg-wallpaper
137
- # name: dsh-mpkg-wallpaper
133
+ ### Option 2: pnpm manual install (pnpm-workspace profile)
138
134
 
139
- # 3. Restart dsh web, then Ctrl+F5 in the browser
135
+ ```bash
136
+ # run in the profile directory (replace <profile> with your profile name, e.g. web)
137
+ pnpm --dir $DSH_HOME/profiles/<profile> add dsh-mpkg-wallpaper
138
+ # restart dsh web, then Ctrl+F5 in the browser
140
139
  ```
141
140
 
142
- > Note: the DSH profile is a pnpm workspace (`pnpm-workspace.yaml`, `nodeLinker: hoisted`),
143
- > so a plugin folder under the profile's `node_modules/` is picked up by pnpm's hoisted
144
- > linking automatically — no manual lockfile edits. Prefer Option 1 (`dsh plugin add`) if
145
- > you want a registry install.
141
+ Also writes into the dependency table, so the market recognizes it. No pnpm available?
142
+ Use Option 1 (`dsh plugin add` wraps pnpm).
146
143
 
147
- ### Option 3: Git clone
144
+ ### Option 3: Git clone (developers / offline)
148
145
 
149
146
  ```bash
150
147
  git clone https://github.com/XHR666/dsh-mpkg-wallpaper.git $DSH_HOME/profiles/node_modules/dsh-mpkg-wallpaper
148
+ # then register in the profile's cordis.patch.yml:
149
+ # - insert:
150
+ # - id: dsh-mpkg-wallpaper
151
+ # name: dsh-mpkg-wallpaper
152
+ # restart to take effect
151
153
  ```
152
154
 
153
- Uninstall: `dsh plugin --profile web remove dsh-mpkg-wallpaper` (or remove the mount line + delete the plugin directory + restart).
154
-
155
- > **Why does the plugin market show this plugin but not in the "installed plugins" list?**
156
- > The market's installed detection reads only the profile's `package.json` dependencies.
157
- > Manual installs (Option 2/3: clone into `node_modules` + `cordis.patch.yml` insert) are
158
- > not recorded there, so the market reports "not installed" — this only affects the market
159
- > display, not the wallpaper feature. To be recognized as installed (and market-managed for
160
- > updates), install via **Option 1** `dsh plugin add` and remove the old manual copy (the
155
+ > Note: Option 3 is a manual placement and is **not** recorded in the dependency table —
156
+ > the market won't report it as installed (market display only; the wallpaper feature is
157
+ > unaffected). For market recognition use Option 1/2, and remove the old manual copy (the
161
158
  > `cordis.patch.yml` insert line + plugin directory) to avoid double-loading the plugin.
162
159
 
160
+ Uninstall: `dsh plugin --profile web remove dsh-mpkg-wallpaper`.
161
+
163
162
 
164
163
  ## Official Docs
165
164
 
@@ -198,6 +197,11 @@ dsh-mpkg-wallpaper/
198
197
  ```
199
198
 
200
199
 
200
+ ## Acknowledgements
201
+
202
+ - [Bil812](https://github.com/Bil812) — proposed wallpaper tint, adaptive text color and full-screen unified-mask appearance ideas in [PR #2](https://github.com/XHR666/dsh-mpkg-wallpaper/pull/2) and maintains a long-running fork. The wallpaper tint, adaptive ink, blue-cleanup and color-picker ideas were absorbed as the plugin's **Aqua experiment** mode (toggles, off by default).
203
+ - [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) community — listing & promotion.
204
+
201
205
  ## Notes for Distribution
202
206
 
203
207
  ### Portability
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  - **视频文件**:直接选择 mp4/webm 文件作为视频背景
17
17
 
18
18
  **🌊 整屏虚化(磨砂)体系**
19
- - **统一虚化(独立分组)**:一个条控制整屏壁纸模糊度(0 = 壁纸清晰,拉高 = 越来越模糊);侧边栏/标题栏白雾厚度、聊天区跟随、新会话按钮跟随独立可调;开启时接管下方各项(界面虚化里的侧边栏磨砂、标题栏磨砂、磨砂模糊条被接管并提示)
19
+ - **统一虚化(独立分组)**:一个条控制整屏壁纸模糊度(0 = 壁纸清晰,拉高 = 越来越模糊);侧边栏白雾厚度、聊天区跟随、新会话按钮跟随独立可调;开启时接管侧边栏磨砂与磨砂模糊条(标题栏不接管,按自己的磨砂条,默认透明)
20
20
  - **界面虚化(独立分组)**:
21
21
  - **虚化对话框**:通用居中窗口 + 聊天输入框(背景磨砂,滚动经过输入框的文字变朦胧)
22
22
  - **虚化设置面板**:DSH 设置面板独立开关 + 程度
@@ -27,6 +27,10 @@
27
27
  **🎬 镜头与外观**
28
28
  - 镜头缩放(10–2000%)与平移、侧边栏/标题栏透出壁纸开关、轻度锐化、Deep diving 背景框
29
29
 
30
+ **🧪 Aqua 实验模式(默认全关,不影响原功能)**
31
+ - 可开关的社区方案实验:**统一雾**(全屏遮罩统一雾色,强度独立滑条)、**面板匹配壁纸色**(自动取色 + 强度滑条 + 自定义取色盘)、**自适应文字色 + 蓝色清理**(品牌色统一,带自定义取色盘)、**深底文字可读增强**、**任务列表磨砂**
32
+ - 设置页顶部 Tab 分类切换(来源/外观/统一虚化/界面虚化/透出壁纸/Aqua/其他)
33
+
30
34
  **🚀 大文件混合模式(hybrid)**
31
35
  - 开启后 mpkg **流式上传到 DSH 宿主** → 磁盘存储 → HTTP Range 流式播放,**支持 >600MB 的大文件**,内存占用极低
32
36
  - 关闭则回到纯浏览器模式(600MB 上限)
@@ -117,47 +121,41 @@
117
121
 
118
122
  ## 安装
119
123
 
120
- ### 方式一:dsh plugin add(推荐)
124
+ 插件已发布到 npm(`dsh-mpkg-wallpaper`)。任选一种:
125
+
126
+ ### 方式一:dsh plugin add(推荐,市场可识别)
121
127
 
122
128
  ```bash
123
129
  dsh plugin --profile web add dsh-mpkg-wallpaper
124
130
  # 重启 dsh web 后浏览器 Ctrl+F5 生效
125
131
  ```
126
132
 
127
- ### 方式二:pnpm 安装(profile 是 pnpm workspace 时的标准做法)
128
-
129
- ```bash
130
- # 1. 把插件目录放到 profile 的 node_modules 下
131
- # (或用 GitHub 下载的 zip 解压)
132
- git clone https://github.com/XHR666/dsh-mpkg-wallpaper.git $DSH_HOME/profiles/web/node_modules/dsh-mpkg-wallpaper
133
- # (若 profile 不在 ~/.dsh/profiles/web,把路径换成你的 profile 目录)
133
+ 从 npm 官方仓库安装,会写入 profile 的 `package.json` 依赖表——插件市场自动识别为「已安装」,并可显示下载量、用市场管理更新。
134
134
 
135
- # 2. 在 profile 的 cordis.patch.yml 注册一行:
136
- # - insert:
137
- # - id: dsh-mpkg-wallpaper
138
- # name: dsh-mpkg-wallpaper
135
+ ### 方式二:pnpm 手动安装(profile 是 pnpm workspace 时)
139
136
 
140
- # 3. 重启 dsh web,浏览器 Ctrl+F5 生效
137
+ ```bash
138
+ # 在 profile 目录下执行(将 <profile> 换成你的 profile 名,如 web)
139
+ pnpm --dir $DSH_HOME/profiles/<profile> add dsh-mpkg-wallpaper
140
+ # 重启 dsh web,浏览器 Ctrl+F5 生效
141
141
  ```
142
142
 
143
- > 注:DSH profile 使用 pnpm workspace(`pnpm-workspace.yaml`,`nodeLinker: hoisted`),
144
- > 插件目录放在 profile 的 `node_modules/` 下即可被 pnpm 的 hoisted 链接识别,
145
- > 无需手动改 lockfile;若你更习惯 registry 安装,用方式一 `dsh plugin add`。
143
+ 同样写入依赖表,市场可识别。若你的环境没有 pnpm,用方式一(`dsh plugin add` 内部就是 pnpm)。
146
144
 
147
- ### 方式三:GitHub 克隆
145
+ ### 方式三:GitHub 克隆(开发者 / 离线场景)
148
146
 
149
147
  ```bash
150
148
  git clone https://github.com/XHR666/dsh-mpkg-wallpaper.git $DSH_HOME/profiles/node_modules/dsh-mpkg-wallpaper
149
+ # 然后在 profile 的 cordis.patch.yml 注册:
150
+ # - insert:
151
+ # - id: dsh-mpkg-wallpaper
152
+ # name: dsh-mpkg-wallpaper
153
+ # 重启后生效
151
154
  ```
152
155
 
153
- 卸载:`dsh plugin --profile web remove dsh-mpkg-wallpaper`(或删除挂载行 + 插件目录 + 重启)。
156
+ > 注:方式三是手动放置,**不会**写入依赖表——插件市场不识别为「已安装」(仅影响市场显示,不影响功能)。要市场识别请用方式一/方式二,并移除旧的手动副本(`cordis.patch.yml` 的 insert 行 + 插件目录),避免同一插件被加载两次。
154
157
 
155
- > **为什么插件市场里显示了本插件、但「已安装插件」列表里没有?**
156
- > 插件市场的已安装检测只读 profile 的 `package.json` 依赖表。方式二/方式三(手动 clone
157
- > 到 `node_modules` + `cordis.patch.yml` insert)不会被依赖表记录,所以市场判为「未安装」
158
- > ——不影响壁纸功能,只是市场显示如此。想被市场识别为已安装(并可用市场管理更新),
159
- > 请用**方式一** `dsh plugin add` 安装,并把旧的手动副本(`cordis.patch.yml` 的 insert 行 +
160
- > 插件目录)移除,避免同一插件被加载两次。
158
+ 卸载:`dsh plugin --profile web remove dsh-mpkg-wallpaper`。
161
159
 
162
160
 
163
161
  ## 官方文档
@@ -197,6 +195,11 @@ dsh-mpkg-wallpaper/
197
195
  ```
198
196
 
199
197
 
198
+ ## 致谢
199
+
200
+ - [Bil812](https://github.com/Bil812) — 在 [PR #2](https://github.com/XHR666/dsh-mpkg-wallpaper/pull/2) 中提出壁纸取色、自适应文字色、全屏统一遮罩等外观方案,并长期维护 fork。其中**壁纸取色、自适应文字色、蓝色清理、取色盘**等思路已吸收为本插件的「Aqua 实验」模式(可开关,默认关)。
201
+ - [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) 社区 — 收录与推广。
202
+
200
203
  ## GitHub 发布说明
201
204
 
202
205
  ### 可移植性(在他人的设备上也能用)
package/lib/client.js CHANGED
@@ -7,6 +7,8 @@ window.__ModuleLoader__.load({
7
7
 
8
8
  let react = require("react");
9
9
 
10
+
11
+
10
12
  // ═══════════════════════════════════════════════════════════════════
11
13
  // 常量
12
14
  // ═══════════════════════════════════════════════════════════════════
@@ -20,7 +22,7 @@ window.__ModuleLoader__.load({
20
22
  const DEFAULT_SHARP = true;
21
23
  const DEFAULT_HEADER = true;
22
24
  const DEFAULT_HEADER_BG = true;
23
- const DEFAULT_HEADER_BLUR_AMOUNT = 80; // 标题栏磨砂程度 0-100%(白雾厚度,独立于整屏虚化)
25
+ const DEFAULT_HEADER_BLUR_AMOUNT = 0; // 标题栏磨砂程度 0-100%(白雾厚度;默认 0=透明,避免 session log 等按钮被白色矩形框包住)
24
26
  const DEFAULT_DIALOG_BLUR = true;
25
27
  const DEFAULT_DIALOG_AMOUNT = 14;
26
28
  // ①(新) 虚化对话框拆三类:通用居中窗口 / 设置面板 / 下载·确认弹窗,各自独立开关+程度
@@ -38,9 +40,24 @@ window.__ModuleLoader__.load({
38
40
  const DEFAULT_UNIFY_TINT = true; // 统一虚化:整屏模糊感由一个独立条控制
39
41
  const DEFAULT_UNIFY_AMOUNT = 30; // 统一虚化程度 0-40:0=清晰,40=强模糊(控制壁纸层 blur)
40
42
  const DEFAULT_CHAT_FOLLOW = true; // ①(新) 统一虚化是否接管聊天区壁纸(开=整屏统一;关=磨砂条独立控制聊天区,统一虚化只管侧边栏/标题栏)
41
- const DEFAULT_SIDEBAR_ALPHA = 55; // ①(新) 统一虚化下侧边栏/标题栏白雾厚度 0-100(独立于不透明度条)
43
+ const DEFAULT_SIDEBAR_ALPHA = 35; // ①(新) 统一虚化下侧边栏/标题栏白雾厚度 0-100(默认 35:顶栏/侧边栏一致且白底淡,session log/模式标签后不会太突兀;用户实测 55 太厚)
42
44
  const DEFAULT_SESSION_FOLLOW = true; // 统一虚化下,「新会话」按钮是否随整屏虚化(关=随面板不透明度)
43
45
  const DEFAULT_HYBRID = true; // ①(新) 大文件混合模式:上传到 DSH 宿主流式播放(>600MB 无限制);关=纯浏览器模式
46
+ // ⑲(新) Aqua 实验模式(借鉴 Bil812 fork,默认全关,不影响原功能):
47
+ // - aquaMask:统一雾(#mpw-mask 全屏遮罩,所有表面共享一种雾色)
48
+ // - aquaTint:面板颜色匹配壁纸主色(48×48 采样)
49
+ // - aquaInk:自适应文字色 + 蓝色清理(brand 覆写为墨色衍生)
50
+ const DEFAULT_AQUA_MASK = false;
51
+ const DEFAULT_AQUA_TINT = false;
52
+ const DEFAULT_AQUA_INK = false;
53
+ // ⑲(新) 深底文字可读增强(默认关;近似方案=全局双色描边,无法精确"只变经过深色处")
54
+ const DEFAULT_AQUA_TEXT_ENHANCE = false;
55
+ // ⑲(新) 任务列表(todo 卡片)磨砂背景(默认关)
56
+ const DEFAULT_TODO_BLUR = false;
57
+ // ⑲(新) 统一雾强度(独立滑条,默认 82%)
58
+ const DEFAULT_AQUA_MASK_ALPHA = 82;
59
+ // ⑲(新) 面板取色强度(壁纸色混合比例 0-100%,默认 45——用户实测默认太淡看不出变化)
60
+ const DEFAULT_AQUA_TINT_STRENGTH = 45;
44
61
  const DEFAULT_ROTATE = false; // ③(新) 壁纸轮换:定时自动切换下一个壁纸
45
62
  const DEFAULT_BRIGHTNESS = 100; // ⑧(新) 画面亮度(50-150%,滤镜)
46
63
  const DEFAULT_FLOAT = false; // ①(新) 悬浮效果:侧边栏/标题栏悬浮卡片(默认关)
@@ -719,6 +736,20 @@ window.__ModuleLoader__.load({
719
736
  else document.body.removeAttribute("data-mpw-sblur");
720
737
  } catch {}
721
738
  try { setupSblurObserver(); } catch {}
739
+ try { setupAquaThemeWatch(); } catch {}
740
+ // ⑲(新) Aqua 实验模式:body 门控 + 遮罩/取色刷新(默认关,不影响原功能)
741
+ try {
742
+ if (aquaOn(section)) document.body.setAttribute("data-mpw-aqua", "");
743
+ else document.body.removeAttribute("data-mpw-aqua");
744
+ if (section.aquaTextEnhance !== void 0 ? !!section.aquaTextEnhance : DEFAULT_AQUA_TEXT_ENHANCE)
745
+ document.body.setAttribute("data-mpw-aqua-text", "");
746
+ else document.body.removeAttribute("data-mpw-aqua-text");
747
+ if (section.todoBlur !== void 0 ? !!section.todoBlur : DEFAULT_TODO_BLUR)
748
+ document.body.setAttribute("data-mpw-todo-blur", "");
749
+ else document.body.removeAttribute("data-mpw-todo-blur");
750
+ refreshAqua();
751
+ if (aquaOn(section)) scheduleAquaTint();
752
+ } catch {}
722
753
  // 2(修正) seam 标记 sidebar root(解除宽度用,参考 seam-stamper)
723
754
  try {
724
755
  const sr = document.querySelector('[class*="sidebarCol"] [class*="root"]');
@@ -735,6 +766,228 @@ window.__ModuleLoader__.load({
735
766
  try { updateClock(); } catch {}
736
767
  }
737
768
 
769
+ // ═══════════════════════════════════════════════════════════════════
770
+ // ⑲(新) Aqua 实验模式(借鉴 Bil812 fork;默认全关,不影响原功能)
771
+ // - 统一雾:#mpw-aqua-mask 全屏覆盖层(z-index:-1,壁纸之上内容之下)
772
+ // - 壁纸取色:48×48 平均色 → --mpw-panel-tint → --mpw-mask-rgb
773
+ // - 自适应文字色 + 蓝色清理:mask 亮度 → 亮字/深字,brand 覆写为墨色
774
+ // ═══════════════════════════════════════════════════════════════════
775
+ let aquaMaskEl = null;
776
+ let aquaTintHooked = new WeakSet();
777
+ let aquaTintSig = "";
778
+ function aquaOn(section) {
779
+ return (section.aquaMask !== void 0 ? !!section.aquaMask : DEFAULT_AQUA_MASK)
780
+ || (section.aquaTint !== void 0 ? !!section.aquaTint : DEFAULT_AQUA_TINT)
781
+ || (section.aquaInk !== void 0 ? !!section.aquaInk : DEFAULT_AQUA_INK);
782
+ }
783
+ function ensureAquaMask() {
784
+ if (aquaMaskEl && aquaMaskEl.isConnected) return aquaMaskEl;
785
+ aquaMaskEl = document.createElement("div");
786
+ aquaMaskEl.id = "mpw-aqua-mask";
787
+ aquaMaskEl.style.cssText = "position:fixed;inset:0;z-index:-1;pointer-events:none;display:none;";
788
+ (document.body || document.documentElement).appendChild(aquaMaskEl);
789
+ return aquaMaskEl;
790
+ }
791
+ function aquaParseHex(hex) {
792
+ const h = String(hex || "").replace("#", "").trim();
793
+ if (!/^[0-9a-fA-F]{3,8}$/.test(h)) return null;
794
+ const full = h.length <= 4 ? h.split("").map((c) => c + c).join("").slice(0, 6) : h;
795
+ return [parseInt(full.slice(0, 2), 16), parseInt(full.slice(2, 4), 16), parseInt(full.slice(4, 6), 16)];
796
+ }
797
+ function aquaMixRgb(a, b, t) {
798
+ return [Math.round(a[0] + (b[0] - a[0]) * t), Math.round(a[1] + (b[1] - a[1]) * t), Math.round(a[2] + (b[2] - a[2]) * t)];
799
+ }
800
+ function aquaHexOf(rgb) {
801
+ return "#" + rgb.map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0")).join("");
802
+ }
803
+ /** 自适应文字色:暗遮罩 → 亮字 / 亮遮罩 → 深字(固定高可读中性色)。 */
804
+ function aquaInkForRgb(rgb) {
805
+ const er = rgb[0], eg = rgb[1], eb = rgb[2];
806
+ const luma = (0.299 * er + 0.587 * eg + 0.114 * eb) / 255;
807
+ return luma <= 0.6
808
+ ? { luma, ink: "#eef1f7", inkSecondary: "#c3cbd8", inkTertiary: "#aab4c4" }
809
+ : { luma, ink: "#10141f", inkSecondary: "#3d4657", inkTertiary: "#5f6a7c" };
810
+ }
811
+ /** 遮罩有效色:自定义色 > 壁纸主色(亮主题掺 35%、暗主题掺 55%)> 主题中性色。 */
812
+ function aquaEffectiveColor(section) {
813
+ const darkTheme = !!(document.body && document.body.hasAttribute("data-ds-dark-theme"));
814
+ const custom = section.aquaColor && /^#[0-9a-fA-F]{3,8}$/.test(section.aquaColor) ? aquaParseHex(section.aquaColor) : null;
815
+ if (custom) return custom;
816
+ const tintOn = section.aquaTint !== void 0 ? !!section.aquaTint : DEFAULT_AQUA_TINT;
817
+ if (tintOn) {
818
+ let raw = "";
819
+ try { raw = getComputedStyle(document.documentElement).getPropertyValue("--mpw-panel-tint").trim(); } catch {}
820
+ const parts = String(raw || "").trim().split(/\s+/).map(Number);
821
+ if (parts.length >= 3 && !parts.some((v) => isNaN(v))) {
822
+ const neutral = darkTheme ? [14, 20, 32] : [255, 255, 255];
823
+ // ⑲(修正) 取色强度可调:aquaTintStrength 0-100(默认 45)
824
+ const strength = Math.max(0, Math.min(100, section.aquaTintStrength !== void 0 ? section.aquaTintStrength : DEFAULT_AQUA_TINT_STRENGTH));
825
+ const ratio = strength / 100;
826
+ return [
827
+ Math.round(ratio * parts[0] + (1 - ratio) * neutral[0]),
828
+ Math.round(ratio * parts[1] + (1 - ratio) * neutral[1]),
829
+ Math.round(ratio * parts[2] + (1 - ratio) * neutral[2])
830
+ ];
831
+ }
832
+ }
833
+ return darkTheme ? [14, 20, 32] : [255, 255, 255];
834
+ }
835
+ /** ink 的反色:深 ink → 白;浅 ink → 深(用于按钮背景/图标保证对比)。 */
836
+ function aquaInkContrast(inkHex) {
837
+ const rgb = aquaParseHex(inkHex);
838
+ if (!rgb) return "#ffffff";
839
+ const luma = (0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]) / 255;
840
+ return luma <= 0.5 ? "#ffffff" : "#10141f";
841
+ }
842
+ /** 自定义品牌色:aquaInkColor 有效时用它做品牌/主按钮色,否则用 ink。 */
843
+ function aquaBrandColor(section) {
844
+ if (section.aquaInkColor && /^#[0-9a-fA-F]{3,8}$/.test(section.aquaInkColor)) return section.aquaInkColor;
845
+ let inkRaw = "";
846
+ try { inkRaw = getComputedStyle(document.documentElement).getPropertyValue("--mpw-aqua-ink").trim(); } catch {}
847
+ return inkRaw || "#10141f";
848
+ }
849
+ /** 刷新 Aqua:设 CSS 变量 + 全屏遮罩背景;关闭时清理。 */
850
+ function refreshAqua() {
851
+ try {
852
+ const s = readSection();
853
+ const enabled = s.enabled !== void 0 ? !!s.enabled : DEFAULT_ENABLED;
854
+ const on = aquaOn(s);
855
+ const root = document.documentElement;
856
+ const el = ensureAquaMask();
857
+ if (!on || !enabled || !s.image) {
858
+ el.style.display = "none";
859
+ for (const p of ["--mpw-aqua-rgb", "--mpw-aqua-ink", "--mpw-aqua-ink-secondary", "--mpw-aqua-ink-tertiary"]) root.style.removeProperty(p);
860
+ aquaTintSig = "";
861
+ return;
862
+ }
863
+ const rgb = aquaEffectiveColor(s);
864
+ const info = aquaInkForRgb(rgb);
865
+ root.style.setProperty("--mpw-aqua-rgb", `${rgb[0]} ${rgb[1]} ${rgb[2]}`);
866
+ root.style.setProperty("--mpw-aqua-ink", info.ink);
867
+ root.style.setProperty("--mpw-aqua-ink-secondary", info.inkSecondary);
868
+ root.style.setProperty("--mpw-aqua-ink-tertiary", info.inkTertiary);
869
+ root.style.setProperty("--mpw-aqua-ink-contrast", aquaInkContrast(info.ink));
870
+ root.style.setProperty("--mpw-aqua-brand-contrast", aquaInkContrast(aquaBrandColor(s)));
871
+ const maskOn = s.aquaMask !== void 0 ? !!s.aquaMask : DEFAULT_AQUA_MASK;
872
+ if (maskOn) {
873
+ const panel = Math.max(0, Math.min(100, s.aquaMaskAlpha !== void 0 ? s.aquaMaskAlpha : DEFAULT_AQUA_MASK_ALPHA)) / 100;
874
+ el.style.background = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${panel})`;
875
+ el.style.display = "";
876
+ } else {
877
+ el.style.display = "none";
878
+ }
879
+ } catch {}
880
+ }
881
+ /** 从当前壁纸抽主色(48×48 平均色)→ --mpw-panel-tint。 */
882
+ function applyAquaTint() {
883
+ try {
884
+ const s = readSection();
885
+ if (!(s.aquaTint !== void 0 ? !!s.aquaTint : DEFAULT_AQUA_TINT)) return;
886
+ const { img, video } = bgElements();
887
+ const src = (video && video.readyState >= 2 && video.videoWidth > 0)
888
+ ? video
889
+ : (img && img.complete && img.naturalWidth > 0 ? img : null);
890
+ if (!src) return;
891
+ const S = 48;
892
+ const canvas = document.createElement("canvas");
893
+ canvas.width = S; canvas.height = S;
894
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
895
+ if (!ctx) return;
896
+ ctx.drawImage(src, 0, 0, S, S);
897
+ const data = ctx.getImageData(0, 0, S, S).data;
898
+ let r = 0, g = 0, b = 0, n = 0;
899
+ for (let i = 0; i < data.length; i += 4) {
900
+ if (data[i + 3] < 128) continue;
901
+ r += data[i]; g += data[i + 1]; b += data[i + 2]; n++;
902
+ }
903
+ if (!n) return;
904
+ const R = Math.round(r / n), G = Math.round(g / n), B = Math.round(b / n);
905
+ const sig = `${R},${G},${B}`;
906
+ if (sig === aquaTintSig) return;
907
+ aquaTintSig = sig;
908
+ document.documentElement.style.setProperty("--mpw-panel-tint", `${R} ${G} ${B}`);
909
+ refreshAqua();
910
+ } catch {}
911
+ }
912
+ /** 监听壁纸加载/播放,周期刷新取色(视频/GIF 节流 2s)。 */
913
+ function scheduleAquaTint() {
914
+ try {
915
+ const { img, video } = bgElements();
916
+ if (!img && !video) return;
917
+ const doTint = () => { try { applyAquaTint(); } catch {} };
918
+ if (img && !aquaTintHooked.has(img)) {
919
+ aquaTintHooked.add(img);
920
+ img.addEventListener("load", doTint, { passive: true });
921
+ }
922
+ if (video && !aquaTintHooked.has(video)) {
923
+ aquaTintHooked.add(video);
924
+ video.addEventListener("loadeddata", doTint, { passive: true });
925
+ let last = 0;
926
+ video.addEventListener("timeupdate", () => {
927
+ const now = Date.now();
928
+ if (now - last < 2000) return;
929
+ last = now;
930
+ doTint();
931
+ }, { passive: true });
932
+ }
933
+ } catch {}
934
+ }
935
+ /** Aqua 开启时的 token 覆盖(mask 色背景 + ink 文字 + 蓝色清理),合并进 applyTokenOverrides。 */
936
+ function aquaTokenOverrides(section) {
937
+ const darkTheme = !!(document.body && document.body.hasAttribute("data-ds-dark-theme"));
938
+ let maskRaw = "";
939
+ try { maskRaw = getComputedStyle(document.documentElement).getPropertyValue("--mpw-aqua-rgb").trim(); } catch {}
940
+ const parts = String(maskRaw || "").trim().split(/\s+/).map(Number);
941
+ if (parts.length < 3 || parts.some((v) => isNaN(v))) return null;
942
+ const rgb = parts;
943
+ const info = aquaInkForRgb(rgb);
944
+ const tinted = (alpha) => `color-mix(in srgb, rgb(var(--mpw-aqua-rgb)) ${Math.round(alpha * 100)}%, transparent)`;
945
+ const out = {
946
+ "--dsw-alias-bg-base": { light: tinted(0.62), dark: tinted(0.62) },
947
+ "--dsw-alias-bg-overlay": { light: tinted(0.72), dark: tinted(0.72) },
948
+ "--dsw-alias-bg-layer-2": { light: tinted(0.72), dark: tinted(0.72) },
949
+ "--dsw-alias-bg-layer-3": { light: tinted(0.72), dark: tinted(0.72) },
950
+ "--dsw-specific-sidebar-fill": { light: tinted(0.85), dark: tinted(0.85) },
951
+ "--dsw-specific-menu": { light: tinted(0.86), dark: tinted(0.86) },
952
+ "--dsw-specific-bubble": { light: tinted(0.84), dark: tinted(0.84) },
953
+ "--dsw-specific-bubble-highlight": { light: tinted(0.92), dark: tinted(0.92) },
954
+ "--dsw-specific-selector": { light: tinted(0.78), dark: tinted(0.78) },
955
+ "--dsw-specific-tip": { light: tinted(0.85), dark: tinted(0.85) },
956
+ "--dsw-specific-input-major": { light: tinted(0.9), dark: tinted(0.9) },
957
+ "--dsw-specific-sidebar-nav-item-active": { light: tinted(0.72), dark: tinted(0.72) },
958
+ "--dsw-specific-sidebar-nav-item-hover": { light: tinted(0.6), dark: tinted(0.6) },
959
+ "--dsw-specific-sidebar-nav-item-active-accent": { light: tinted(0.6), dark: tinted(0.6) },
960
+ "--dsw-alias-bg-module-platform": { light: tinted(0.86), dark: tinted(0.86) },
961
+ "--dsw-alias-bg-multi-select": { light: tinted(0.82), dark: tinted(0.82) },
962
+ "--dsw-alias-button-elevated-fill": { light: tinted(0.78), dark: tinted(0.78) },
963
+ "--dsw-alias-button-floating-fill": { light: tinted(0.85), dark: tinted(0.85) },
964
+ "--dsw-alias-button-ghost-active-fill": { light: tinted(0.7), dark: tinted(0.7) },
965
+ "--dsw-alias-button-ghost-active-border": { light: tinted(0.6), dark: tinted(0.6) },
966
+ "--dsw-alias-button-contrast-fill": { light: tinted(0.9), dark: tinted(0.9) },
967
+ "--dsw-alias-interactive-bg-selected": { light: tinted(0.68), dark: tinted(0.68) },
968
+ "--dsw-alias-interactive-bg-hover": { light: tinted(0.55), dark: tinted(0.55) },
969
+ "--dsw-alias-interactive-bg-hover-solid": { light: tinted(0.72), dark: tinted(0.72) },
970
+ "--dsw-alias-tooltip-bg": { light: `color-mix(in srgb, rgb(var(--mpw-aqua-rgb)) 96%, var(--dsw-static-neutral-bluish-850))`, dark: `color-mix(in srgb, rgb(var(--mpw-aqua-rgb)) 96%, var(--dsw-static-neutral-bluish-850))` },
971
+ "--dsw-alias-toast-bg": { light: tinted(0.9), dark: tinted(0.9) },
972
+ "--dsw-alias-markdown-inline-code": { light: tinted(0.24), dark: tinted(0.24) },
973
+ "--dsw-alias-markdown-code-block": { light: tinted(0.32), dark: tinted(0.32) }
974
+ };
975
+ const inkOn = section.aquaInk !== void 0 ? !!section.aquaInk : DEFAULT_AQUA_INK;
976
+ if (inkOn) {
977
+ // ⑲(修正) 品牌色支持自定义(aquaInkColor 取色器):默认用 ink,
978
+ // 自定义色时按钮/发送键/插件文字用自定义色,保证对比(用户实测默认 ink 让发送键看不清)
979
+ const brand = aquaBrandColor(section);
980
+ out["--dsw-alias-label-primary"] = { light: info.ink, dark: info.ink };
981
+ out["--dsw-alias-label-secondary"] = { light: info.inkSecondary, dark: info.inkSecondary };
982
+ out["--dsw-alias-label-tertiary"] = { light: info.inkTertiary, dark: info.inkTertiary };
983
+ out["--dsw-alias-brand-primary"] = { light: brand, dark: brand };
984
+ out["--dsw-alias-brand-text"] = { light: brand, dark: brand };
985
+ out["--dsw-alias-button-info-fill"] = { light: brand, dark: brand };
986
+ out["--dsw-alias-button-info-hover"] = { light: brand, dark: brand };
987
+ }
988
+ return out;
989
+ }
990
+
738
991
  /**
739
992
  * ⑭ 用 token override 实现对话框/弹层半透明(参考 ui-theme-background-custom 方案)。
740
993
  * DSH 的弹层/菜单/对话框背景由 --dsw-alias-bg-overlay 驱动;主画布由
@@ -803,6 +1056,13 @@ window.__ModuleLoader__.load({
803
1056
  try { if (tokenDisposer) { tokenDisposer(); tokenDisposer = null; } } catch {}
804
1057
  return;
805
1058
  }
1059
+ // ⑲(新) Aqua 实验模式:开时用 mask 色覆盖主要背景/文字 token(在现有 override 之后生效)
1060
+ try {
1061
+ if (aquaOn(section)) {
1062
+ const aquaOv = aquaTokenOverrides(section);
1063
+ if (aquaOv) Object.assign(overrides, aquaOv);
1064
+ }
1065
+ } catch {}
806
1066
  try {
807
1067
  if (tokenDisposer) { tokenDisposer(); tokenDisposer = null; }
808
1068
  tokenDisposer = ctx.theme.overrideTokens("@local/dsh-mpkg-wallpaper-tokens", overrides);
@@ -1102,10 +1362,12 @@ ${frostedLayers}
1102
1362
  // ①(修正) 标题栏磨砂。**绝不能给 header 本体加 backdrop-filter**——
1103
1363
  // header 有 fixed 子元素(子代理展开面板/后台任务条),backdrop-filter 会成为
1104
1364
  // 它们的 containing block,导致面板定位错乱(用户实测 bug)。
1105
- // ①(修正) 标题栏雾底:统一虚化开 → 跟随 sidebarAlpha(标题栏磨砂程度条被接管);
1106
- // 关 → 由「标题栏磨砂程度」条控制。headerBg/headerBlur 开关仍独立(关=纯白)。
1365
+ // ①(修正) 标题栏雾底:unify 开 → **透明**(session log 按钮/标准模式标签
1366
+ // 后的白框 = 标题栏白底,用户两次要求去掉;标题栏直接透出模糊壁纸);
1367
+ // unify 关 → 按「标题栏磨砂程度」条(默认 0=透明,需要雾底自行拉高)。
1368
+ // 侧边栏白雾由「侧边栏/标题栏透明度」条控制(仅侧边栏)。
1107
1369
  const hblurAmt = section.headerBlurAmount !== void 0 ? section.headerBlurAmount : DEFAULT_HEADER_BLUR_AMOUNT;
1108
- const hdrAlpha = unifyTint ? uAlpha : Math.max(0, Math.min(100, hblurAmt));
1370
+ const hdrAlpha = unifyTint ? 0 : Math.max(0, Math.min(100, hblurAmt));
1109
1371
  const hdrBg = `color-mix(in srgb, var(--dsw-static-neutral-bluish-950) ${hdrAlpha}%, transparent)`;
1110
1372
  css += `
1111
1373
  .wSkVaW_header {
@@ -1456,6 +1718,77 @@ ${unifyTint ? `body:not([data-ds-dark-theme]) [data-cordis-panel] [class*="row"]
1456
1718
  .hHd-Xa_regionArea, .wSkVaW_scrollBody, .ydkMvW_body { backdrop-filter: none !important; }
1457
1719
  }
1458
1720
  `;
1721
+ // ⑲(新) Aqua 实验模式:文字色/品牌蓝兜底 + 弹层模糊(token override 之外)
1722
+ if (aquaOn(section)) {
1723
+ css += `
1724
+ /* ── Aqua 实验模式:自适应文字色 + 蓝色清理(可开关,默认关) ── */
1725
+ body[data-mpw-aqua] {
1726
+ --dsw-alias-label-primary: var(--mpw-aqua-ink, inherit);
1727
+ --dsw-alias-label-secondary: var(--mpw-aqua-ink-secondary, inherit);
1728
+ --dsw-alias-label-tertiary: var(--mpw-aqua-ink-tertiary, inherit);
1729
+ --dsw-alias-label-caption: var(--mpw-aqua-ink-tertiary, inherit);
1730
+ --dsw-alias-label-dimmed: var(--mpw-aqua-ink-tertiary, inherit);
1731
+ --dsw-alias-brand-primary: var(--mpw-aqua-ink, inherit);
1732
+ --dsw-alias-brand-text: var(--mpw-aqua-ink, inherit);
1733
+ --dsw-alias-state-business-primary: var(--mpw-aqua-ink-secondary, inherit);
1734
+ }
1735
+ /* ⑲(修正) Aqua 模式下弹层背景被 mask 色半透明化,必须配 backdrop blur 防文字叠压
1736
+ (用户实测:加号/命令/权限/模型/上下文选择器透明但无模糊 → 文字叠在一起) */
1737
+ body[data-mpw-aqua] [role="menu"],
1738
+ body[data-mpw-aqua] [role="listbox"],
1739
+ body[data-mpw-aqua] [role="combobox"],
1740
+ body[data-mpw-aqua] [data-dsh-surface] {
1741
+ backdrop-filter: blur(14px) !important;
1742
+ -webkit-backdrop-filter: blur(14px) !important;
1743
+ }
1744
+ /* ⑲(修正) 发送键对比:背景用品牌色(ink 或自定义),图标反色 → 不再"只剩圆圈"
1745
+ (用户实测默认 ink 下发送键背景变浅、箭头看不清) */
1746
+ body[data-mpw-aqua] [data-composer-card] [class*="primary"],
1747
+ body[data-mpw-aqua] [data-slot*="composer"] [class*="primary"] {
1748
+ background-color: var(--dsw-alias-brand-primary, var(--mpw-aqua-ink)) !important;
1749
+ color: var(--mpw-aqua-brand-contrast, var(--mpw-aqua-ink-contrast)) !important;
1750
+ }
1751
+ /* ⑲(修正) 本插件弹窗(冲突/下载/确认)文字保持主题对比色,不跟 ink
1752
+ (用户实测:aquaInk 开时冲突弹窗文字与背景叠色看不清) */
1753
+ body[data-mpw-aqua] .mpw_dialog { color: var(--dsw-static-neutral-bluish-850) !important; }
1754
+ body[data-mpw-aqua] body[data-ds-dark-theme] .mpw_dialog { color: var(--dsw-static-neutral-bluish-100) !important; }
1755
+ body[data-mpw-aqua] .mpw_dialog .mpw_title,
1756
+ body[data-mpw-aqua] .mpw_dialog .mpw_label,
1757
+ body[data-mpw-aqua] .mpw_dialog .mpw_hint,
1758
+ body[data-mpw-aqua] .mpw_dialog .mpw_value { color: inherit !important; }
1759
+ `;
1760
+ }
1761
+ // ⑲(新) 深底文字可读增强(aquaTextEnhance,默认关):
1762
+ // 尝试过两种开源方案均不理想:① 双色 text-shadow 描边(浅底上像"喷墨打印机");
1763
+ // ② mix-blend-mode difference(全局反色,粉色/彩色文字全被反转,用户实测不可用)。
1764
+ // 最终方案:**只加白色细描边**——浅色背景上白边不可见(不破坏浅底),
1765
+ // 深色/黑色背景上自动给文字勾勒白色轮廓(深底可读)。这是唯一不破坏浅色背景的近似。
1766
+ // 说明:浏览器无法精确实现"只变经过深色处的字"(需逐字采样背景像素,滚动动态内容下不可靠)。
1767
+ if (section.aquaTextEnhance !== void 0 ? !!section.aquaTextEnhance : false) {
1768
+ css += `
1769
+ /* ── 深底文字可读增强(实验,默认关):白色细描边(浅底不可见,深底提亮轮廓) ── */
1770
+ body[data-mpw-aqua-text] [data-conversation-scroll] :is(p, li, h1, h2, h3, h4, td, th) {
1771
+ text-shadow: 0 0 1px rgba(255,255,255,.85), 0 1px 1px rgba(255,255,255,.55) !important;
1772
+ }
1773
+ `;
1774
+ }
1775
+ // ⑲(新) 任务列表(todo 卡片)磨砂背景:收纳/展开状态都模糊(类似标题栏/侧边栏磨砂)。
1776
+ // 独立开关(todoBlur,默认关)。
1777
+ // ②(修正) 去掉 70% 白色底条(用户实测像"灰色滤镜"+ 白色底条难看),
1778
+ // 改为纯 backdrop blur:背景透明,背后内容(壁纸/聊天区)真模糊 = 磨砂玻璃。
1779
+ if (section.todoBlur !== void 0 ? !!section.todoBlur : false) {
1780
+ css += `
1781
+ /* ── 任务列表磨砂(实验,默认关):todo 卡片纯模糊,无白色底条 ── */
1782
+ body[data-mpw-todo-blur] [data-tool="todo_write"] {
1783
+ backdrop-filter: blur(16px) !important;
1784
+ -webkit-backdrop-filter: blur(16px) !important;
1785
+ background-color: transparent !important;
1786
+ }
1787
+ body[data-mpw-todo-blur] [data-tool="todo_write"] * {
1788
+ background-color: transparent !important;
1789
+ }
1790
+ `;
1791
+ }
1459
1792
  return css + buildUiCss(section, dlgFrosted);
1460
1793
  }
1461
1794
 
@@ -1477,6 +1810,55 @@ ${unifyTint ? `body:not([data-ds-dark-theme]) [data-cordis-panel] [class*="row"]
1477
1810
  color: var(--dsw-alias-label-primary); letter-spacing: 0.02em;
1478
1811
  }
1479
1812
  .mpw_section:first-of-type { margin-top: 10px; }
1813
+ /* ⑳(修正) 取色盘色块(点开取色器的按钮) */
1814
+ .mpw_colorSwatch {
1815
+ flex: none; width: 84px; height: 38px; box-sizing: border-box;
1816
+ border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px;
1817
+ cursor: pointer; position: relative;
1818
+ }
1819
+ .mpw_colorSwatch::after {
1820
+ content: ""; position: absolute; inset: 0; border-radius: 8px;
1821
+ border: 1px solid rgba(0,0,0,.15); pointer-events: none;
1822
+ }
1823
+ /* ⑳(修正) 顶部 Tab 条:圆角导航栏 + 下划线平滑移动(indicator 平移)+ 内容真滑动 */
1824
+ .mpw_tabBar {
1825
+ display: flex; gap: 2px; align-items: center;
1826
+ position: relative;
1827
+ border-radius: 12px; padding: 4px 6px;
1828
+ margin-bottom: 8px; position: sticky; top: 0; z-index: 5;
1829
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 65%, transparent);
1830
+ border: 1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 60%, transparent);
1831
+ }
1832
+ body[data-ds-dark-theme] .mpw_tabBar {
1833
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 45%, transparent);
1834
+ }
1835
+ .mpw_tab {
1836
+ flex: none; font: inherit; color: var(--dsw-alias-label-secondary);
1837
+ cursor: pointer; white-space: nowrap; background: 0 0; border: none;
1838
+ padding: 6px 12px; font-size: 13px; border-radius: 8px;
1839
+ }
1840
+ .mpw_tab:hover { color: var(--dsw-alias-label-primary); background: color-mix(in srgb, var(--dsw-alias-interactive-bg-hover) 60%, transparent); }
1841
+ .mpw_tabActive {
1842
+ color: var(--dsw-alias-brand-primary, #4f6ef7);
1843
+ font-weight: 600;
1844
+ }
1845
+ /* 下划线指示条:切换时 left/width 平滑平移(useEffect 测量激活 tab) */
1846
+ .mpw_tabIndicator {
1847
+ position: absolute; bottom: 0; height: 2px; border-radius: 2px;
1848
+ background: var(--dsw-alias-brand-primary, #4f6ef7);
1849
+ transition: left .22s cubic-bezier(.4,0,.2,1), width .22s cubic-bezier(.4,0,.2,1);
1850
+ left: 0; width: 0; pointer-events: none;
1851
+ }
1852
+ /* 内容区:外层固定裁剪(overflow hidden),内层 tabRow translateX 滑动(翻页效果)。
1853
+ ⑳(修正) transform 必须加在内层——加在外层会连裁剪区一起左移,内容全空(用户实测)。 */
1854
+ .mpw_tabBody {
1855
+ overflow: hidden; min-height: 60px;
1856
+ }
1857
+ .mpw_tabRow {
1858
+ display: flex;
1859
+ transition: transform .24s cubic-bezier(.4,0,.2,1);
1860
+ will-change: transform;
1861
+ }
1480
1862
  .mpw_field { display: flex; flex-direction: column; gap: 6px; padding: 8px 4px; border-top: 1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 45%, transparent); }
1481
1863
  .mpw_label { font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-secondary); }
1482
1864
  .mpw_inline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
@@ -1702,7 +2084,11 @@ body[data-mpw-modal] [role="dialog"] {
1702
2084
  } catch {}
1703
2085
  try {
1704
2086
  document.querySelectorAll("body > *").forEach((el) => {
1705
- if (el.classList && el.classList.contains("mpw-bgWrap")) return; // 自己的壁纸层
2087
+ // ①(修正) 排除自己的元素:壁纸层(bgWrap)、Aqua 全屏遮罩(aqua-mask)、时钟。
2088
+ // 曾把自己的 mask 误报为冲突(fullscreen-bg:DIV → 自动关闭壁纸功能,用户实测)。
2089
+ const ownId = el && el.id;
2090
+ if (ownId === BG_WRAP_ID || ownId === "mpw-aqua-mask" || ownId === "mpw-clock") return;
2091
+ if (el.classList && el.classList.contains("mpw-bgWrap")) return; // 自己的壁纸层(class 兜底)
1706
2092
  const cs = getComputedStyle(el);
1707
2093
  const z = Number(cs.zIndex);
1708
2094
  if (cs.position === "fixed" && isFinite(z) && z < 0) {
@@ -1831,6 +2217,9 @@ body[data-mpw-modal] [role="dialog"] {
1831
2217
  });
1832
2218
  }
1833
2219
 
2220
+ // ⑳(新) Tab 顺序(内容区 translateX 滑动用)
2221
+ const TAB_ORDER = ["source", "appearance", "unify", "blur", "show", "aqua", "other"];
2222
+
1834
2223
  function MpkgSection(props) {
1835
2224
  try {
1836
2225
  const { t } = props;
@@ -1840,6 +2229,14 @@ body[data-mpw-modal] [role="dialog"] {
1840
2229
  return null;
1841
2230
  })();
1842
2231
  const [section, setSection] = react.useState(readSection());
2232
+ // ⑳(新) 设置页顶部 Tab(来源/外观/统一虚化/界面虚化/透出/Aqua/其他),减少滚动。
2233
+ // Tab 切换只改 display,控件始终挂载(hooks 稳定,不能条件卸载 sliderRow/toggleRow)。
2234
+ const [settingsTab, setSettingsTab] = react.useState("source");
2235
+ // ②(修正) Tab 切换:内容区 translateX 滑动(TAB_ORDER 顺序)
2236
+ const switchTab = (id) => {
2237
+ if (id === settingsTab) return;
2238
+ setSettingsTab(id);
2239
+ };
1843
2240
  const [mpkgMeta, setMpkgMeta] = react.useState(initMeta); // { name, key, info, entryName, slot }
1844
2241
  const [busy, setBusy] = react.useState(false);
1845
2242
  const [hint, setHint] = react.useState("");
@@ -1878,6 +2275,19 @@ body[data-mpw-modal] [role="dialog"] {
1878
2275
  fetch(HOST_BASE + "/ping", { method: "GET" }).then((r) => setHostOk(!!r.ok)).catch(() => setHostOk(false));
1879
2276
  }, []);
1880
2277
 
2278
+ // ⑳(修正) Tab 下划线平滑移动:测量激活 tab 位置/宽度 → indicator 平移过去
2279
+ react.useEffect(() => {
2280
+ try {
2281
+ const bar = document.querySelector('[data-mpw-tabbar]');
2282
+ const ind = document.querySelector('[data-mpw-tabind]');
2283
+ const active = bar && bar.querySelector(".mpw_tabActive");
2284
+ if (bar && ind && active) {
2285
+ ind.style.left = active.offsetLeft + "px";
2286
+ ind.style.width = active.offsetWidth + "px";
2287
+ }
2288
+ } catch {}
2289
+ }, [settingsTab]);
2290
+
1881
2291
  // ④ 总开关:开启时若有冲突 → 弹窗确认
1882
2292
  const onMaster = (v) => {
1883
2293
  if (v && conflicts.length && !section.forceEnabled) {
@@ -1899,6 +2309,111 @@ body[data-mpw-modal] [role="dialog"] {
1899
2309
  applyFromStorage();
1900
2310
  return next;
1901
2311
  };
2312
+ // ⑲(新) 内置取色盘(自绘 HSV,无外部依赖/无加载副作用):
2313
+ // 曾内联 vanilla-picker,但其 UMD 在模块加载时立即操作 DOM 且覆盖 module.exports,
2314
+ // 导致 dsh 加载插件崩溃(cannot get property "onChange" without inject)——已改为
2315
+ // 点击时创建 DOM 的自绘取色器(色相条 + 饱和/亮度面板 + hex 输入)。
2316
+ let pickerInst = null;
2317
+ const openPicker = (key, currentColor) => {
2318
+ try {
2319
+ if (pickerInst) { pickerInst.remove(); pickerInst = null; }
2320
+ const parent = document.querySelector('[data-mpw-picker-anchor="' + key + '"]');
2321
+ if (!parent) return;
2322
+ const start = currentColor && /^#[0-9a-fA-F]{6}$/.test(currentColor) ? currentColor : "#808080";
2323
+ let h = 0, s = 0.5, v = 0.5, drag = null;
2324
+ const hexToHsv = (hex) => {
2325
+ const n = parseInt(hex.slice(1), 16);
2326
+ const r = ((n >> 16) & 255) / 255, g = ((n >> 8) & 255) / 255, bl = (n & 255) / 255;
2327
+ const mx = Math.max(r, g, bl), mn = Math.min(r, g, bl), dlt = mx - mn;
2328
+ let hh = 0;
2329
+ if (dlt !== 0) {
2330
+ if (mx === r) hh = ((g - bl) / dlt) % 6;
2331
+ else if (mx === g) hh = (bl - r) / dlt + 2;
2332
+ else hh = (r - g) / dlt + 4;
2333
+ hh *= 60; if (hh < 0) hh += 360;
2334
+ }
2335
+ return { h: hh, s: mx === 0 ? 0 : dlt / mx, v: mx };
2336
+ };
2337
+ const hsvToHex = (hh, ss, vv) => {
2338
+ const c = vv * ss, x = c * (1 - Math.abs(((hh / 60) % 2) - 1)), m = vv - c;
2339
+ let r = 0, g = 0, bl = 0;
2340
+ if (hh < 60) { r = c; g = x; } else if (hh < 120) { r = x; g = c; } else if (hh < 180) { g = c; bl = x; }
2341
+ else if (hh < 240) { g = x; bl = c; } else if (hh < 300) { r = x; bl = c; } else { r = c; bl = x; }
2342
+ const to = (q) => Math.round((q + m) * 255).toString(16).padStart(2, "0");
2343
+ return "#" + to(r) + to(g) + to(bl);
2344
+ };
2345
+ const { h: ih, s: is, v: iv } = hexToHsv(start);
2346
+ h = ih; s = is; v = iv;
2347
+ const wrap = document.createElement("div");
2348
+ wrap.className = "mpw_pickerWrap";
2349
+ wrap.style.cssText = "position:fixed;z-index:4000;background:var(--dsw-static-neutral-bluish-00,#fff);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:10px;box-shadow:0 12px 40px rgba(0,0,0,.35);width:224px;font-family:var(--dsw-font-family);";
2350
+ // 色相条
2351
+ const hueBar = document.createElement("div");
2352
+ hueBar.style.cssText = "height:14px;border-radius:7px;background:linear-gradient(90deg,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00);cursor:pointer;position:relative;";
2353
+ const hueKnob = document.createElement("div");
2354
+ hueKnob.style.cssText = "position:absolute;top:-3px;width:8px;height:20px;border-radius:4px;border:2px solid #fff;box-shadow:0 0 4px rgba(0,0,0,.5);pointer-events:none;";
2355
+ hueBar.appendChild(hueKnob);
2356
+ // SV 面板
2357
+ const svPanel = document.createElement("div");
2358
+ svPanel.style.cssText = "height:120px;border-radius:8px;cursor:pointer;position:relative;margin-top:8px;";
2359
+ const svKnob = document.createElement("div");
2360
+ svKnob.style.cssText = "position:absolute;width:12px;height:12px;border-radius:50%;border:2px solid #fff;box-shadow:0 0 4px rgba(0,0,0,.5);pointer-events:none;transform:translate(-50%,-50%);";
2361
+ svPanel.appendChild(svKnob);
2362
+ // hex 输入 + 预览 + 确定
2363
+ const bottom = document.createElement("div");
2364
+ bottom.style.cssText = "display:flex;gap:6px;align-items:center;margin-top:8px;";
2365
+ const preview = document.createElement("div");
2366
+ preview.style.cssText = "width:26px;height:26px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2);";
2367
+ const hexInput = document.createElement("input");
2368
+ hexInput.style.cssText = "flex:1;min-width:0;height:28px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:0 8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;outline:none;";
2369
+ hexInput.addEventListener("focus", () => { hexInput.style.borderColor = "var(--dsw-alias-label-primary)"; hexInput.style.boxShadow = "0 0 0 1px var(--dsw-alias-label-primary)"; });
2370
+ hexInput.addEventListener("blur", () => { hexInput.style.borderColor = "var(--dsw-alias-border-l2)"; hexInput.style.boxShadow = "none"; });
2371
+ hexInput.value = start;
2372
+ const okBtn = document.createElement("button");
2373
+ okBtn.textContent = t("default") === "默认" ? "确定" : "OK";
2374
+ okBtn.style.cssText = "height:28px;padding:0 12px;border:none;border-radius:6px;background:#3964fe;color:#fff;font:inherit;font-size:12px;cursor:pointer;";
2375
+ bottom.appendChild(preview); bottom.appendChild(hexInput); bottom.appendChild(okBtn);
2376
+ wrap.appendChild(hueBar); wrap.appendChild(svPanel); wrap.appendChild(bottom);
2377
+ document.body.appendChild(wrap);
2378
+ const refresh = () => {
2379
+ svPanel.style.background = "linear-gradient(180deg, #fff 0%, hsl(" + h + ",100%,50%) 50%, #000 100%)";
2380
+ const cur = hsvToHex(h, s, v);
2381
+ preview.style.background = cur;
2382
+ hexInput.value = cur;
2383
+ hueKnob.style.left = (h / 360 * 100) + "%";
2384
+ svKnob.style.left = (s * 100) + "%";
2385
+ svKnob.style.top = ((1 - v) * 100) + "%";
2386
+ };
2387
+ const setFromInput = () => {
2388
+ const val = hexInput.value.trim();
2389
+ if (/^#[0-9a-fA-F]{6}$/.test(val)) { const c = hexToHsv(val); h = c.h; s = c.s; v = c.v; refresh(); }
2390
+ };
2391
+ hexInput.addEventListener("change", setFromInput);
2392
+ const pickPos = (e, el, vertical) => {
2393
+ const r = el.getBoundingClientRect();
2394
+ let p = (vertical ? e.clientY - r.top : e.clientX - r.left) / (vertical ? r.height : r.width);
2395
+ p = Math.max(0, Math.min(1, p));
2396
+ return p;
2397
+ };
2398
+ hueBar.addEventListener("mousedown", (e) => { drag = "hue"; h = pickPos(e, hueBar, false) * 360; refresh(); });
2399
+ svPanel.addEventListener("mousedown", (e) => { drag = "sv"; s = pickPos(e, svPanel, false); v = 1 - pickPos(e, svPanel, true); refresh(); });
2400
+ window.addEventListener("mousemove", (e) => {
2401
+ if (drag === "hue") { h = pickPos(e, hueBar, false) * 360; refresh(); }
2402
+ else if (drag === "sv") { s = pickPos(e, svPanel, false); v = 1 - pickPos(e, svPanel, true); refresh(); }
2403
+ });
2404
+ window.addEventListener("mouseup", () => { drag = null; });
2405
+ okBtn.addEventListener("click", () => { commit({ [key]: hexInput.value.trim() }, true); pickerInst = null; wrap.remove(); });
2406
+ // 定位在色块附近
2407
+ const pr = parent.getBoundingClientRect();
2408
+ wrap.style.left = Math.min(window.innerWidth - 240, pr.right + 8) + "px";
2409
+ wrap.style.top = Math.max(0, pr.top - 10) + "px";
2410
+ refresh();
2411
+ pickerInst = wrap;
2412
+ // 点击外部关闭
2413
+ const outside = (e) => { if (!wrap.contains(e.target) && e.target !== parent) { wrap.remove(); pickerInst = null; document.removeEventListener("mousedown", outside); } };
2414
+ setTimeout(() => document.addEventListener("mousedown", outside), 0);
2415
+ } catch {}
2416
+ };
1902
2417
  // ④(新) 扫描本地壁纸库(Steam 自动发现,host 提供)
1903
2418
  const scanLibrary = async () => {
1904
2419
  if (!hostOk) { showError(t("lib.noHost")); return; }
@@ -1950,11 +2465,15 @@ body[data-mpw-modal] [role="dialog"] {
1950
2465
  // ①(新) 目录选择器:打开并列出指定路径的子目录(跨平台,host 浏览)
1951
2466
  const openDirPicker = async (path) => {
1952
2467
  setDirPick(true); // ⑦(修正) 打开弹窗(之前漏了这行导致"浏览"无反应)
1953
- setDirPath(path);
2468
+ setDirPath(path || "/");
1954
2469
  try {
1955
- const r = await fetch(HOST_BASE + "/list-dirs?path=" + encodeURIComponent(path));
2470
+ // 空路径 → host 返回主目录(home);显示用 "/" 兜底,实际路径由 host 规范化
2471
+ const r = await fetch(HOST_BASE + "/list-dirs?path=" + encodeURIComponent(path || ""));
1956
2472
  const d = await r.json();
1957
2473
  setDirSubs(d.ok && d.subdirs ? d.subdirs : []);
2474
+ // ①(修正) 用 host 规范化的实际路径更新 dirPath(空/相对路径 → 绝对),
2475
+ // 否则进子目录会拼出相对路径 → 列表空/上级错乱(用户实测浏览功能坏)
2476
+ if (d.ok && d.dir) setDirPath(d.dir);
1958
2477
  if (d.ok && d.home) setDirHome(d.home);
1959
2478
  if (d.ok && d.platform) setDirPlatform(d.platform);
1960
2479
  } catch { setDirSubs([]); }
@@ -2087,6 +2606,7 @@ body[data-mpw-modal] [role="dialog"] {
2087
2606
  popoverBlur: DEFAULT_POPOVER_BLUR, popoverAmount: DEFAULT_POPOVER_AMOUNT,
2088
2607
  maskBlur: DEFAULT_MASK_BLUR, maskAmount: DEFAULT_MASK_AMOUNT,
2089
2608
  unifyTint: DEFAULT_UNIFY_TINT, unifyAmount: DEFAULT_UNIFY_AMOUNT, sidebarAlpha: DEFAULT_SIDEBAR_ALPHA, chatFollow: DEFAULT_CHAT_FOLLOW, sessionFollow: DEFAULT_SESSION_FOLLOW,
2609
+ aquaMask: DEFAULT_AQUA_MASK, aquaTint: DEFAULT_AQUA_TINT, aquaInk: DEFAULT_AQUA_INK, aquaColor: "", aquaInkColor: "", aquaTextEnhance: DEFAULT_AQUA_TEXT_ENHANCE, todoBlur: DEFAULT_TODO_BLUR, aquaMaskAlpha: DEFAULT_AQUA_MASK_ALPHA, aquaTintStrength: DEFAULT_AQUA_TINT_STRENGTH,
2090
2610
  hybrid: DEFAULT_HYBRID, roundCompat: DEFAULT_ROUND_COMPAT,
2091
2611
  rotate: DEFAULT_ROTATE, rotateMin: 5, customDirPath: "", brightness: DEFAULT_BRIGHTNESS, float: DEFAULT_FLOAT,
2092
2612
  thinkBg: DEFAULT_THINK_BG,
@@ -2493,9 +3013,26 @@ body[data-mpw-modal] [role="dialog"] {
2493
3013
  };
2494
3014
 
2495
3015
  return h("div", { className: "mpw_row" }, [
3016
+ // ①(修正) 标题/描述在 Tab 条上方
2496
3017
  h("div", { className: "mpw_title" }, t("title")),
2497
3018
  h("p", { className: "mpw_desc" }, t("desc")),
2498
-
3019
+ // ②(修正) 圆角导航栏 + 下划线平滑移动(indicator 平移)+ 内容真滑动(translateX)
3020
+ h("div", { className: "mpw_tabBar", "data-mpw-tabbar": "" }, [
3021
+ h("div", { className: "mpw_tabIndicator", "data-mpw-tabind": "" }),
3022
+ h("button", { className: "mpw_tab" + (settingsTab === "source" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("source") }, t("sec.source")),
3023
+ h("button", { className: "mpw_tab" + (settingsTab === "appearance" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("appearance") }, t("sec.appearance")),
3024
+ h("button", { className: "mpw_tab" + (settingsTab === "unify" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("unify") }, t("sec.unify")),
3025
+ h("button", { className: "mpw_tab" + (settingsTab === "blur" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("blur") }, t("sec.blur")),
3026
+ h("button", { className: "mpw_tab" + (settingsTab === "show" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("show") }, t("sec.show")),
3027
+ h("button", { className: "mpw_tab" + (settingsTab === "aqua" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("aqua") }, t("sec.aqua")),
3028
+ h("button", { className: "mpw_tab" + (settingsTab === "other" ? " mpw_tabActive" : ""), type: "button", onClick: () => switchTab("other") }, t("sec.other")),
3029
+ ]),
3030
+ // 内容区:flex 行 + translateX 滑动(真翻页;所有 tab 内容始终挂载,hooks 稳定)
3031
+ h("div", { className: "mpw_tabBody" }, [
3032
+ // 内层 flex 行:translateX 滑动(外层裁剪区固定,否则整体左移内容全空——用户实测)
3033
+ h("div", { className: "mpw_tabRow", style: { transform: "translateX(-" + TAB_ORDER.indexOf(settingsTab) * 100 + "%)" } }, [
3034
+ // source 组
3035
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
2499
3036
  // ═══ 背景来源 ═══
2500
3037
  h("div", { className: "mpw_section" }, t("sec.source")),
2501
3038
 
@@ -2690,7 +3227,9 @@ body[data-mpw-modal] [role="dialog"] {
2690
3227
  h("input", { ref: imgRef, type: "file", accept: "image/*,.gif,.mp4,.webm,.mkv,.mov", style: { display: "none" }, onChange: onMedia })
2691
3228
  ]),
2692
3229
 
3230
+ ]),
2693
3231
  // ═══ 外观 ═══
3232
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
2694
3233
  h("div", { className: "mpw_section" }, t("sec.appearance")),
2695
3234
  // ②(新) 外观组说明:各项作用一目了然
2696
3235
  h("p", { className: "mpw_hint" }, t("sec.appearance.desc")),
@@ -2765,7 +3304,9 @@ body[data-mpw-modal] [role="dialog"] {
2765
3304
  ])
2766
3305
  ]),
2767
3306
 
3307
+ ]),
2768
3308
  // ═══ 统一虚化(独立大标题分组)═══
3309
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
2769
3310
  h("div", { className: "mpw_section" }, t("sec.unify")),
2770
3311
  h("p", { className: "mpw_hint" }, t("sec.unify.desc")),
2771
3312
 
@@ -2789,7 +3330,9 @@ body[data-mpw-modal] [role="dialog"] {
2789
3330
  h("div", { style: { display: (section.unifyTint !== void 0 ? !!section.unifyTint : DEFAULT_UNIFY_TINT) ? "" : "none" } },
2790
3331
  toggleRow(t("sessionFollow"), t("sessionFollow.desc"), "sessionFollow", DEFAULT_SESSION_FOLLOW)),
2791
3332
 
3333
+ ]),
2792
3334
  // ═══ 界面虚化 ═══
3335
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
2793
3336
  h("div", { className: "mpw_section" }, t("sec.blur")),
2794
3337
  h("p", { className: "mpw_hint" }, t("sec.blur.desc")),
2795
3338
 
@@ -2823,7 +3366,9 @@ body[data-mpw-modal] [role="dialog"] {
2823
3366
  h("div", { style: { display: (section.maskBlur !== void 0 ? !!section.maskBlur : DEFAULT_MASK_BLUR) ? "" : "none" } },
2824
3367
  sliderRow(t("maskBlurAmount"), "maskAmount", 0, 40, "px", 1, DEFAULT_MASK_AMOUNT)),
2825
3368
 
3369
+ ]),
2826
3370
  // ═══ 透出壁纸 ═══
3371
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
2827
3372
  h("div", { className: "mpw_section" }, t("sec.show")),
2828
3373
  h("p", { className: "mpw_hint" }, t("sec.show.desc")),
2829
3374
 
@@ -2834,19 +3379,12 @@ body[data-mpw-modal] [role="dialog"] {
2834
3379
  toggleRow(t("headerBg"), t("headerBg.desc"), "headerBg", DEFAULT_HEADER_BG),
2835
3380
 
2836
3381
  // ①(重做) 标题栏磨砂:归到「标题栏透出壁纸」下面,透出关闭时隐藏。
2837
- // ①(修正) 统一虚化开启时,「标题栏磨砂程度」条被整屏虚化接管(禁用+提示);
3382
+ // ②(修正) 不再被统一虚化接管:磨砂程度条始终可调(默认 0=透明)。
2838
3383
  // 开关(headerBg/headerBlur)仍独立:开关关 = 纯白背景。
2839
3384
  h("div", { style: { display: (section.headerBg !== void 0 ? !!section.headerBg : DEFAULT_HEADER_BG) ? "" : "none" } },
2840
3385
  toggleRow(t("headerBlur"), t("headerBlur.desc"), "headerBlur", DEFAULT_HEADER)),
2841
- h("div", { style: {
2842
- display: (section.headerBg !== void 0 ? !!section.headerBg : DEFAULT_HEADER_BG) && (section.headerBlur !== void 0 ? !!section.headerBlur : DEFAULT_HEADER) ? "" : "none",
2843
- opacity: (section.unifyTint !== void 0 ? !!section.unifyTint : DEFAULT_UNIFY_TINT) ? 0.45 : 1,
2844
- pointerEvents: (section.unifyTint !== void 0 ? !!section.unifyTint : DEFAULT_UNIFY_TINT) ? "none" : "auto"
2845
- } },
3386
+ h("div", { style: { display: (section.headerBg !== void 0 ? !!section.headerBg : DEFAULT_HEADER_BG) && (section.headerBlur !== void 0 ? !!section.headerBlur : DEFAULT_HEADER) ? "" : "none" } },
2846
3387
  sliderRow(t("headerBlurAmount"), "headerBlurAmount", 0, 100, "%", 1, DEFAULT_HEADER_BLUR_AMOUNT)),
2847
- (section.unifyTint !== void 0 ? !!section.unifyTint : DEFAULT_UNIFY_TINT)
2848
- ? h("p", { className: "mpw_hint" }, t("headerBlur.overridden"))
2849
- : null,
2850
3388
 
2851
3389
  // ①(新) 侧边栏磨砂(Aqua 方案):与标题栏磨砂同类(区域自身玻璃化),
2852
3390
  // 弹窗打开时自动摘除(防弹窗被模糊层困住);统一虚化开启时被整屏虚化接管
@@ -2861,7 +3399,56 @@ body[data-mpw-modal] [role="dialog"] {
2861
3399
  ? h("p", { className: "mpw_hint" }, t("sidebarBlur.overridden"))
2862
3400
  : null,
2863
3401
 
3402
+ ]),
3403
+ // ═══ Aqua 实验(默认全关,不影响原功能)═══
3404
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
3405
+ h("div", { className: "mpw_section" }, t("sec.aqua")),
3406
+ h("p", { className: "mpw_hint" }, t("sec.aqua.desc")),
3407
+ // ①(修正) Aqua 方案来源:跳转 Bil812 的 PR #2(致谢可视化)
3408
+ h("div", { className: "mpw_inline", style: { marginBottom: 4 } }, [
3409
+ h("a", { className: "mpw_link", href: "https://github.com/XHR666/dsh-mpkg-wallpaper/pull/2", target: "_blank", rel: "noopener" }, "→ " + t("aqua.credit"))
3410
+ ]),
3411
+ toggleRow(t("aquaMask"), t("aquaMask.desc"), "aquaMask", DEFAULT_AQUA_MASK),
3412
+ // ⑲(新) 统一雾强度:独立滑条(用户实测没有单独控制条,mask 透明度只能靠「面板不透明度」但该条不存在)
3413
+ h("div", { style: { display: (section.aquaMask !== void 0 ? !!section.aquaMask : DEFAULT_AQUA_MASK) ? "" : "none" } },
3414
+ sliderRow(t("aquaMaskAlpha"), "aquaMaskAlpha", 0, 100, "%", 1, DEFAULT_AQUA_MASK_ALPHA)),
3415
+ toggleRow(t("aquaTint"), t("aquaTint.desc"), "aquaTint", DEFAULT_AQUA_TINT),
3416
+ h("div", { style: { display: (section.aquaTint !== void 0 ? !!section.aquaTint : DEFAULT_AQUA_TINT) ? "" : "none" } },
3417
+ sliderRow(t("aquaTintStrength"), "aquaTintStrength", 0, 100, "%", 1, DEFAULT_AQUA_TINT_STRENGTH)),
3418
+ toggleRow(t("aquaInk"), t("aquaInk.desc"), "aquaInk", DEFAULT_AQUA_INK),
3419
+ // ⑲(新) 取色器:遮罩自定义色 / 品牌(发送键等主色)自定义色
3420
+ h("div", { className: "mpw_field" }, [
3421
+ h("label", { className: "mpw_label" }, t("aquaColor")),
3422
+ h("div", { className: "mpw_inline" }, [
3423
+ h("button", {
3424
+ className: "mpw_colorSwatch", "data-mpw-picker-anchor": "aquaColor", type: "button",
3425
+ style: { background: (section.aquaColor && /^#[0-9a-fA-F]{6}$/.test(section.aquaColor) ? section.aquaColor : "#808080") },
3426
+ onClick: () => openPicker("aquaColor", section.aquaColor)
3427
+ }),
3428
+ h("button", { className: "mpw_miniBtn", type: "button", onClick: () => commit({ aquaColor: "" }, true) }, t("aquaColorReset")),
3429
+ h("span", { className: "mpw_hint" }, t("aquaColor.hint"))
3430
+ ])
3431
+ ]),
3432
+ h("div", { className: "mpw_field" }, [
3433
+ h("label", { className: "mpw_label" }, t("aquaInkColor")),
3434
+ h("div", { className: "mpw_inline" }, [
3435
+ h("button", {
3436
+ className: "mpw_colorSwatch", "data-mpw-picker-anchor": "aquaInkColor", type: "button",
3437
+ style: { background: (section.aquaInkColor && /^#[0-9a-fA-F]{6}$/.test(section.aquaInkColor) ? section.aquaInkColor : "#808080") },
3438
+ onClick: () => openPicker("aquaInkColor", section.aquaInkColor)
3439
+ }),
3440
+ h("button", { className: "mpw_miniBtn", type: "button", onClick: () => commit({ aquaInkColor: "" }, true) }, t("aquaColorReset")),
3441
+ h("span", { className: "mpw_hint" }, t("aquaInkColor.hint"))
3442
+ ])
3443
+ ]),
3444
+ // ⑲(新) 深底文字可读增强(近似方案:全局双色描边)
3445
+ toggleRow(t("aquaTextEnhance"), t("aquaTextEnhance.desc"), "aquaTextEnhance", DEFAULT_AQUA_TEXT_ENHANCE),
3446
+ // ⑲(新) 任务列表磨砂(收纳/展开统一模糊)
3447
+ toggleRow(t("todoBlur"), t("todoBlur.desc"), "todoBlur", DEFAULT_TODO_BLUR),
3448
+
3449
+ ]),
2864
3450
  // ═══ 其他 ═══
3451
+ h("div", { style: { flex: "0 0 100%", minWidth: "100%", boxSizing: "border-box", paddingRight: "4px" } }, [
2865
3452
  h("div", { className: "mpw_section" }, t("sec.other")),
2866
3453
 
2867
3454
  // ⑦ 轻度锐化(可能影响 GIF 流畅度)
@@ -2888,7 +3475,9 @@ body[data-mpw-modal] [role="dialog"] {
2888
3475
  : null
2889
3476
  ]),
2890
3477
  updState && updState.error ? h("p", { className: "mpw_hint mpw_err" }, t("update.fail") + updState.error) : null,
2891
- updState && updState.hasUpdate ? h("p", { className: "mpw_hint" }, t("update.found") + updState.localVersion + " → " + updState.remoteVersion) : null,
3478
+ updState && updState.hasUpdate && updState.sameVersionDiff
3479
+ ? h("p", { className: "mpw_hint mpw_err" }, t("update.diff"))
3480
+ : (updState && updState.hasUpdate ? h("p", { className: "mpw_hint" }, t("update.found") + updState.localVersion + " → " + updState.remoteVersion) : null),
2892
3481
  updState && updState.applied ? h("p", { className: "mpw_hint" }, t("update.applied")) : null,
2893
3482
  updState && updState.hasUpdate === false ? h("p", { className: "mpw_hint" }, t("update.latest")) : null
2894
3483
  ]),
@@ -2992,6 +3581,9 @@ body[data-mpw-modal] [role="dialog"] {
2992
3581
  ])
2993
3582
  ])
2994
3583
  ]) : null
3584
+ ]),
3585
+ ]),
3586
+ ]),
2995
3587
  ]);
2996
3588
  } catch (err) {
2997
3589
  // 渲染错误边界:任何渲染异常只显示错误信息,绝不整页空白
@@ -3061,10 +3653,30 @@ body[data-mpw-modal] [role="dialog"] {
3061
3653
  "sec.blur": "界面虚化",
3062
3654
  "sec.blur.desc": "各类弹层/面板打开时的背景虚化:对话框(通用居中窗口+聊天输入框)、设置面板、下载确认弹窗各自独立;弹层=菜单/下拉/提示;遮罩=弹层背后的全屏背景;侧边栏磨砂=侧边栏自身玻璃化",
3063
3655
  "sec.unify": "统一虚化",
3064
- "sec.unify.desc": "整屏所有控件的模糊感由一组设置统一管理(一个条全管侧边栏/标题栏/聊天区);开启后下方「界面虚化」里的侧边栏磨砂被接管。关闭则各区域单独调节",
3656
+ "sec.unify.desc": "整屏所有控件的模糊感由一组设置统一管理(一个条全管侧边栏/标题栏/聊天区);开启后「界面虚化」里的侧边栏磨砂被接管(标题栏不再接管,按自己的磨砂条)。关闭则各区域单独调节",
3065
3657
  "sec.show": "透出壁纸",
3066
3658
  "sec.show.desc": "控制对应区域是否显示壁纸:关=纯色不透明",
3067
3659
  "sec.other": "其他",
3660
+ "sec.aqua": "Aqua 实验",
3661
+ "sec.aqua.desc": "外观方案来自 Bil812(PR #2)的构想,已采用并全部做成独立开关(默认全关,不影响原功能):统一雾 = 全屏遮罩让所有表面共享一种雾色;面板取色 = 颜色跟随壁纸主色;自适应文字 = 文字色随背景亮度变化 + 蓝色清理",
3662
+ "aqua.credit": "Bil812 的 PR #2(方案来源)",
3663
+ "aquaMask": "统一雾(全屏遮罩)",
3664
+ "aquaMask.desc": "所有表面(侧边栏/标题栏/聊天区/按钮)共享一种雾色(强度由下方「统一雾强度」条控制),不再分区白雾;关 = 保持现有分区雾",
3665
+ "aquaMaskAlpha": "统一雾强度",
3666
+ "aquaTint": "面板颜色匹配壁纸",
3667
+ "aquaTint.desc": "自动采样壁纸主色作为面板底色(视频/GIF 每 2 秒刷新);强度由下方滑条控制;关 = 使用主题中性色",
3668
+ "aquaTintStrength": "面板取色强度",
3669
+ "aquaInk": "自适应文字色 + 蓝色清理",
3670
+ "aquaColor": "遮罩自定义色(取色盘)",
3671
+ "aquaColor.hint": "设置后优先于壁纸取色;点「默认」恢复自动",
3672
+ "aquaColorReset": "默认",
3673
+ "aquaInkColor": "品牌/发送键自定义色(取色盘)",
3674
+ "aquaInkColor.hint": "发送键/主按钮/插件文字用它(默认 = 自适应墨色);设深色可让发送键箭头清晰",
3675
+ "aquaTextEnhance": "深底文字可读增强",
3676
+ "aquaTextEnhance.desc": "给聊天区文字加双色描边,黑色/深色背景上也能看清(近似方案:无法精确到'只变经过深色处的字';默认关)",
3677
+ "todoBlur": "任务列表磨砂",
3678
+ "todoBlur.desc": "对话中列出的任务(todo 卡片)背景模糊,收纳/展开状态统一(类似标题栏/侧边栏磨砂;默认关)",
3679
+ "aquaInk.desc": "文字颜色随遮罩亮度自适应(亮底深字/暗底浅字),并把品牌蓝等硬编码色统一为墨色衍生色",
3068
3680
  "mpkg.pick": "选择 .mpkg 文件",
3069
3681
  "mpkg.busy": "解析中…",
3070
3682
  "mpkg.hint": "支持 Wallpaper Engine 的 .mpkg 包;此位置也可直接选择 mp4/webm 视频文件;视频类壁纸自动播放内嵌 mp4",
@@ -3096,6 +3708,7 @@ body[data-mpw-modal] [role="dialog"] {
3096
3708
  "update.applying": "更新中…",
3097
3709
  "update.found": "发现新版本:",
3098
3710
  "update.latest": "已是最新版本",
3711
+ "update.diff": "本地与 GitHub 代码存在内容差异(版本号相同,可能是本地有未推送的改动)——推送后即一致",
3099
3712
  "update.applied": "更新完成!请重启 dsh web 并 Ctrl+F5 生效",
3100
3713
  "update.fail": "检查失败:",
3101
3714
  "update.warnTitle": "新版本发布未满 24 小时",
@@ -3130,14 +3743,14 @@ body[data-mpw-modal] [role="dialog"] {
3130
3743
  "headerBlur": "标题栏磨砂",
3131
3744
  "headerBg": "标题栏透出壁纸",
3132
3745
  "headerBg.desc": "关闭后标题栏为纯白(暗色主题为纯深色)不透明,不再显示壁纸",
3133
- "headerBlur.desc": "标题栏半透明透出(已模糊的)壁纸,磨砂程度独立可调(下方滑条),即使整屏虚化调 0 也保持雾底保证文字可读。需先开启「标题栏透出壁纸」",
3746
+ "headerBlur.desc": "标题栏透出壁纸,磨砂程度由下方滑条控制(默认 0 = 透明,session log 等按钮不会被白色矩形框包住;拉高可加白雾保证文字可读)。需先开启「标题栏透出壁纸」",
3134
3747
  "headerBlurAmount": "标题栏磨砂程度",
3135
- "headerBlur.overridden": "统一虚化开启中:标题栏磨砂程度由「整屏虚化程度」接管(白雾跟随侧边栏/标题栏透明度条);关闭统一虚化后恢复",
3748
+
3136
3749
  "unifyTint": "统一虚化",
3137
- "unifyTint.desc": "开启后,侧边栏和标题栏获得类似聊天框的毛玻璃虚化(整块模糊、无缝隙,只模糊它们背后的内容,壁纸其他地方保持清晰),强度由「整屏虚化程度」条控制;表面白雾厚度由「侧边栏/标题栏透明度」条控制。关闭后各区域单独调节",
3750
+ "unifyTint.desc": "开启后,侧边栏获得类似聊天框的毛玻璃虚化(整块模糊、无缝隙),强度由「整屏虚化程度」条控制;侧边栏表面白雾厚度由「侧边栏透明度」条控制;标题栏始终按自己的磨砂条(默认透明)。关闭后各区域单独调节",
3138
3751
  "unifyAmount": "整屏虚化程度",
3139
3752
  "sidebarAlpha": "侧边栏/标题栏透明度",
3140
- "sidebarAlpha.desc": "统一虚化开启时:侧边栏和标题栏表面的白雾厚度(0 = 全透明透出模糊壁纸,100 = 实心)。与「整屏虚化程度」解耦,可单独调",
3753
+ "sidebarAlpha.desc": "统一虚化开启时:侧边栏表面的白雾厚度(0 = 全透明透出模糊壁纸,100 = 实心)。与「整屏虚化程度」解耦,可单独调;标题栏不再跟随(按自己的磨砂条)",
3141
3754
  "chatFollow": "聊天区跟随整屏虚化",
3142
3755
  "chatFollow.desc": "统一虚化开启时:开 = 聊天区壁纸模糊也随「整屏虚化程度」(磨砂条被接管禁用);关 = 磨砂条恢复可调,聊天区壁纸由磨砂条控制(统一虚化只虚化侧边栏/标题栏)",
3143
3756
  "sessionFollow": "新会话按钮跟随面板不透明度",
@@ -3231,10 +3844,30 @@ body[data-mpw-modal] [role="dialog"] {
3231
3844
  "sec.blur": "UI blur",
3232
3845
  "sec.blur.desc": "Backdrop blur when each popup layer opens: dialogs (generic center windows + chat input), the settings panel, and download/confirm popups each have their own switch; popovers = menus/dropdowns/tooltips; mask = the full-screen dim behind popups; sidebar frost = the sidebar itself becomes glass",
3233
3846
  "sec.unify": "Unified blur",
3234
- "sec.unify.desc": "One set of controls rules the frosted feel of every surface (sidebar/titlebar/chat via one slider); when on, sidebar frost below is taken over. Off = each area adjusts separately",
3847
+ "sec.unify.desc": "One set of controls rules the frosted feel of every surface (sidebar/titlebar/chat via one slider); when on, sidebar frost below is taken over (the title bar is not taken over - it follows its own frost slider). Off = each area adjusts separately",
3235
3848
  "sec.show": "Show wallpaper",
3236
3849
  "sec.show.desc": "Whether the corresponding area shows the wallpaper: off = solid color, opaque",
3237
3850
  "sec.other": "Other",
3851
+ "sec.aqua": "Aqua experiment",
3852
+ "sec.aqua.desc": "Appearance ideas from Bil812 (PR #2), adopted and made into independent toggles (all OFF by default, original features untouched): unified fog = full-screen mask, every surface shares one fog color; panel tint = colors follow the wallpaper dominant color; adaptive ink = text follows background brightness + blue cleanup",
3853
+ "aqua.credit": "Bil812 PR #2 (idea source)",
3854
+ "aquaMask": "Unified fog (full-screen mask)",
3855
+ "aquaMask.desc": "Every surface (sidebar/title bar/chat/buttons) shares one fog color (strength by the Unified-fog-strength slider below) instead of per-area fog; off = keep the current per-area fog",
3856
+ "aquaMaskAlpha": "Unified fog strength",
3857
+ "aquaTint": "Panel colors match wallpaper",
3858
+ "aquaTint.desc": "Auto-samples the wallpaper's dominant color as the panel base (videos/GIFs refresh every 2s); strength by the slider below; off = theme neutral colors",
3859
+ "aquaTintStrength": "Panel tint strength",
3860
+ "aquaInk": "Adaptive text color + blue cleanup",
3861
+ "aquaColor": "Custom mask color (picker)",
3862
+ "aquaColor.hint": "When set, takes priority over wallpaper tint; Default restores auto",
3863
+ "aquaColorReset": "Default",
3864
+ "aquaInkColor": "Custom brand / send-button color (picker)",
3865
+ "aquaInkColor.hint": "Send button / primary buttons / plugin text use it (default = adaptive ink); a dark color keeps the send arrow visible",
3866
+ "aquaTextEnhance": "Dark-background text readability",
3867
+ "aquaTextEnhance.desc": "Adds a dual-color text outline to chat text so it stays readable over black/dark backgrounds (approximation - cannot limit to text passing over dark areas only; off by default)",
3868
+ "todoBlur": "Task list frost",
3869
+ "todoBlur.desc": "Frosted background for the task (todo) cards in the conversation, collapsed and expanded alike (like the title-bar/sidebar frost; off by default)",
3870
+ "aquaInk.desc": "Text color adapts to mask brightness (dark text on light / light on dark) and hard-coded brand blues are unified to ink-derived colors",
3238
3871
  "mpkg.pick": "Choose .mpkg file",
3239
3872
  "mpkg.busy": "Parsing…",
3240
3873
  "mpkg.hint": "Wallpaper Engine .mpkg packages; you can also pick an mp4/webm video file here; video wallpapers play their embedded mp4",
@@ -3266,6 +3899,7 @@ body[data-mpw-modal] [role="dialog"] {
3266
3899
  "update.applying": "Updating…",
3267
3900
  "update.found": "New version found: ",
3268
3901
  "update.latest": "Already up to date",
3902
+ "update.diff": "Local code differs from GitHub (same version — probably un-pushed local changes); push to align",
3269
3903
  "update.applied": "Update done! Restart dsh web and Ctrl+F5",
3270
3904
  "update.fail": "Check failed: ",
3271
3905
  "update.warnTitle": "New version released <24h ago",
@@ -3300,11 +3934,11 @@ body[data-mpw-modal] [role="dialog"] {
3300
3934
  "headerBlur": "Frost the title bar",
3301
3935
  "headerBg": "Show wallpaper behind the title bar",
3302
3936
  "headerBg.desc": "Off makes the title bar solid white (solid dark in dark theme), no wallpaper behind it",
3303
- "headerBlur.desc": "Title bar semi-transparent over the (blurred) wallpaper; frosted amount adjustable via the slider below and kept even when full-screen blur is 0, so text stays readable. Needs \"Show wallpaper behind the title bar\" on",
3937
+ "headerBlur.desc": "Title bar shows the wallpaper; frosted amount via the slider below (default 0 = transparent, so the session-log button is not wrapped in a white rectangle; raise it for a readable fog). Needs \"Show wallpaper behind the title bar\" on",
3304
3938
  "headerBlurAmount": "Title bar frost amount",
3305
- "headerBlur.overridden": "Unified blur is on: the title-bar frost amount is taken over by the Full-screen blur degree (fog follows the sidebar/title-bar opacity slider); turn unified blur off to restore it",
3939
+
3306
3940
  "unifyTint": "Unify blur",
3307
- "unifyTint.desc": "On: the sidebar and title bar get a chat-box-like frosted blur (one seamless layer, no seams; only what's behind them is blurred, the wallpaper stays sharp elsewhere), strength controlled by the Full-screen blur degree slider; surface white-fog thickness by the Sidebar/title-bar opacity slider. Off = per-area control",
3941
+ "unifyTint.desc": "On: the sidebar gets a chat-box-like frosted blur (one seamless layer, no seams); strength by the Full-screen blur degree; sidebar white-fog thickness by the Sidebar opacity slider; the title bar always follows its own frost slider (transparent by default). Off = per-area control",
3308
3942
  "unifyAmount": "Full-screen blur degree",
3309
3943
  "sidebarAlpha": "Sidebar / title-bar opacity",
3310
3944
  "sidebarAlpha.desc": "When unified blur is on: white-fog thickness on the sidebar and title bar (0 = fully transparent showing blurred wallpaper, 100 = solid). Decoupled from the blur degree, adjustable independently",
@@ -3389,12 +4023,18 @@ body[data-mpw-modal] [role="dialog"] {
3389
4023
  // ①(新) 侧边栏磨砂摘除:监听居中弹窗出现/消失,body 打 data-mpw-sblur-off。
3390
4024
  // backdrop-filter 会把 sidebarCol 变成 fixed 弹窗的 containing block(困住弹窗),
3391
4025
  // 弹窗打开时摘除侧边栏模糊、关闭即恢复。不用 :has()(Firefox 层叠 bug,见 E 块注释)。
4026
+ // ②(修正) 只摘除 **sidebarCol 内** 的弹窗:backdrop-filter 只困住 sidebarCol 的后代弹窗。
4027
+ // 用户实测:打开「上下文占用」小弹窗(不在 sidebarCol 内)也被摘除,导致统一虚化的
4028
+ // 侧边栏/标题栏模糊失效(session log 框随之消失)——已修正为只匹配 sidebarCol 内的
4029
+ // role=dialog(如设置面板,它在侧边栏 footArea 里)。
3392
4030
  let sblurObserver = null;
3393
4031
  function setupSblurObserver() {
3394
4032
  if (sblurObserver !== null) return;
3395
4033
  const check = () => {
3396
4034
  try {
3397
- const hasDlg = !!document.querySelector('[role="dialog"], [role="alertdialog"]');
4035
+ const hasDlg = !!document.querySelector(
4036
+ '[class*="sidebarCol"] [role="dialog"], [class*="sidebarCol"] [role="alertdialog"]'
4037
+ );
3398
4038
  if (hasDlg) document.body.setAttribute("data-mpw-sblur-off", "");
3399
4039
  else document.body.removeAttribute("data-mpw-sblur-off");
3400
4040
  } catch {}
@@ -3406,6 +4046,24 @@ body[data-mpw-modal] [role="dialog"] {
3406
4046
  check();
3407
4047
  }
3408
4048
 
4049
+ // ⑲(修正) Aqua 主题切换监听:深色/浅色切换时重算遮罩色与自适应文字色
4050
+ //(用户实测:aquaInk 开时切换主题,文字色卡在旧主题——黑字黑底/白字白底看不清)。
4051
+ let aquaThemeWatch = null;
4052
+ function setupAquaThemeWatch() {
4053
+ if (aquaThemeWatch !== null) return;
4054
+ const onTheme = () => {
4055
+ try {
4056
+ refreshAqua();
4057
+ const s = readSection();
4058
+ if (aquaOn(s)) applyTokenOverrides(pluginCtx, s);
4059
+ } catch {}
4060
+ };
4061
+ try {
4062
+ aquaThemeWatch = new MutationObserver(onTheme);
4063
+ aquaThemeWatch.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] });
4064
+ } catch { aquaThemeWatch = null; }
4065
+ }
4066
+
3409
4067
  function applyInner(ctx) {
3410
4068
  // 背景 DOM 常驻
3411
4069
  ensureBgDom();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mpkg-wallpaper",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
4
  "description": "DSH Web 壁纸引擎 Wallpaper Engine mpkg 背景插件:浏览器内直接解析 .mpkg(preview.gif 动态背景/内嵌 mp4 视频/多时段切换),整屏统一虚化/对话框/弹层/遮罩独立虚化、镜头缩放平移、时钟、冲突检测。",
5
5
  "private": false,
6
6
  "type": "module",
@@ -33,10 +33,7 @@
33
33
  }
34
34
  },
35
35
  "peerDependencies": {
36
- "react": "^18.2.0",
37
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
38
- "@deepseek-ai/schemastery": "^3.18.1",
39
- "@deepseek-ai/cordis": "^4.0.1"
36
+ "react": "^18.2.0"
40
37
  },
41
38
  "license": "MIT",
42
39
  "keywords": [