@linxin666/dsh-client-ui-skin-center 0.3.20 → 0.3.22
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/contracts/semantic-attrs-v1.md +14 -3
- package/lib/client.js +168 -36
- package/lib/client.js.map +1 -1
- package/lib/index.js +29 -20
- package/package.json +1 -1
- package/skins/blue-fantasy/patches.css +377 -0
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
| `data-dsh-wallpaper-active` | html + body(body/html 级,另行管理) | WE 壁纸挂载期间置 `true`,卸载 / 禁用清除;供皮肤 CSS 与壁纸中和规则锚定(#734) |
|
|
46
46
|
| `data-dsh-wallpaper-surface` | 官方 shell 全视口背景元素 + 侧栏工作区淡化条(元素级) | `WallpaperController.markWallpaperSurfaces()` 在 WE 壁纸挂载期间打标(全视口 bg-base 背景 + `data-slot="sidebar.workspaces"` 内渐变淡化条),命中 `html[data-dsh-wallpaper-active] [data-dsh-wallpaper-surface]` 中和;卸载清除,不含哈希类依赖(#734) |
|
|
47
47
|
|
|
48
|
-
## part 组(
|
|
48
|
+
## part 组(79 行,含各 owner 行)
|
|
49
49
|
|
|
50
50
|
shell 区域(owner: shell):
|
|
51
51
|
|
|
@@ -70,6 +70,9 @@ family / 插件区域:
|
|
|
70
70
|
| `column` | task-board | 状态列;`section[data-status]` |
|
|
71
71
|
| `card` | task-board | 任务卡;列内 `[data-status]` 条目 |
|
|
72
72
|
| `detail` | task-board | 任务详情面板 |
|
|
73
|
+
| `tag-filter` | task-board | 标签筛选条;`[data-dsh-taskboard-board] [data-dsh-part="tag-filter"]` |
|
|
74
|
+
| `tag-chip` | task-board | 筛选条内的标签胶囊;`[data-dsh-part="tag-chip"]`,`data-tag-tone` 为 0-5 调色板槽 |
|
|
75
|
+
| `tag-badge` | task-board | 卡片上的标签徽章;`[data-dsh-part="tag-badge"]`,`data-tag-tone` 同上 |
|
|
73
76
|
| `tab-bar` / `tab` | ssh | 页签条/页签;`[role="tablist"]` / `[role="tab"]` |
|
|
74
77
|
| `host-table` / `host-row` | ssh | 主机表/行;`[data-dsh-ssh-view]` 内 table/tr |
|
|
75
78
|
| `terminal` | ssh | xterm 终端;面板内 termContainer(.xterm 辅锚) |
|
|
@@ -113,13 +116,15 @@ family / 插件区域:
|
|
|
113
116
|
| `bubble` | miku-pet | 对话气泡;`[data-dsh-part="bubble"]` |
|
|
114
117
|
| `float` | miku-pet | 互动飘字;`[data-dsh-part="float"]` |
|
|
115
118
|
| `header` | usage | 使用统计分区头部(当前提供方 + 刷新钮);`[data-dsh-plugin="usage"] [data-dsh-part="header"]` |
|
|
116
|
-
| `tabs` / `tab` | usage |
|
|
119
|
+
| `tabs` / `tab` | usage | 用量/个人套餐/Token 银行页签;`[role="tablist"]` / `[role="tab"]` |
|
|
117
120
|
| `today-card` | usage | 今日用量统计卡;`[data-dsh-part="today-card"]` |
|
|
118
121
|
| `provider-list` / `provider-row` | usage | 今日分 provider 用量列表 / 余额行;卡片内行容器 |
|
|
119
122
|
| `balance-card` | usage | 各 provider 余额卡;`[data-dsh-part="balance-card"]` |
|
|
120
123
|
| `trend-card` / `usage-chart` | usage | 近 30 天卡 / 其中的提供方-模型条形图;`[data-dsh-part="trend-card"]` 内 `[data-dsh-part="usage-chart"]` |
|
|
121
124
|
| `settings-row` | usage | 插件设置行;`[data-dsh-part="settings-row"]` |
|
|
122
125
|
| `plan-card` / `plan-window` | usage | 套餐卡 / 套餐窗口行(个人套餐页签);`[data-dsh-part="plan-card"]` 内窗口行 |
|
|
126
|
+
| `bank-card` | usage | Token 银行卡(鲸元券,无官方用量时为空状态);`[data-dsh-part="bank-card"]` |
|
|
127
|
+
| `voucher-preview` | usage | 票面 canvas 容器;bank-card 内 `[data-dsh-part="voucher-preview"]` |
|
|
123
128
|
| `panel` | model-capabilities | 提供方卡片能力扩展区根;`[data-dsh-plugin="model-capabilities"][data-dsh-part="panel"]` |
|
|
124
129
|
| `toggle` | model-capabilities | 扩展区折叠头按钮;panel 内 `button[data-dsh-part="toggle"]` |
|
|
125
130
|
| `model-row` / `model-toggle` | model-capabilities | 逐模型能力行与其展开按钮;panel 内 `li[data-dsh-part="model-row"]` 及其中 `button[data-dsh-part="model-toggle"]` |
|
|
@@ -128,8 +133,13 @@ family / 插件区域:
|
|
|
128
133
|
| `save` / `reset` / `disable` / `enable` / `reload` | model-capabilities | 扩展区动作按钮(保存 / 重置 / 禁用此提供方 / 启用 / 重新读取);panel 内裸值按钮 |
|
|
129
134
|
| `disabled-state` | model-capabilities | 已禁用提供方的卡片提示区(含启用按钮);panel 内 `[data-dsh-part="disabled-state"]` |
|
|
130
135
|
| `disabled-footer` / `disabled-row` | model-capabilities | Models 页底部存档区与其行;`settings.models.footer` 槽内 `section[data-dsh-part="disabled-footer"]` 与其中 `li[data-dsh-part="disabled-row"]` |
|
|
136
|
+
| `lever` | liangshen | 首页输入框内的梁神模式拨杆根(模型选择器左侧);`[data-dsh-plugin="liangshen"][data-dsh-part="lever"]`,状态由 `data-state`(`on` / `off` / `locked` / `missing`)锚定 |
|
|
137
|
+
| `lever-track` | liangshen | 拨杆底座槽(臂的转动轨道);lever 内 `[data-dsh-part="lever-track"]` |
|
|
138
|
+
| `lever-arm` | liangshen | 拨杆臂(拉杆 + 球头,随状态转动);lever 内 `[data-dsh-part="lever-arm"]` |
|
|
139
|
+
| `lever-burst` | liangshen | 拨下命中后的中奖特效浮层(闪光 / 冲击环 / 火花 / 横幅);`[data-dsh-part="lever-burst"]`,`prefers-reduced-motion` 下退化为淡出 |
|
|
140
|
+
| `lever-banner` | liangshen | 特效中的梁神横幅(模式名 + 文言文/二进制/摩斯三行);burst 内 `[data-dsh-part="lever-banner"]` |
|
|
131
141
|
|
|
132
|
-
## plugin 组(
|
|
142
|
+
## plugin 组(15 个)
|
|
133
143
|
|
|
134
144
|
| data-dsh-plugin | owner | 锚定方式 |
|
|
135
145
|
| --- | --- | --- |
|
|
@@ -147,6 +157,7 @@ family / 插件区域:
|
|
|
147
157
|
| `usage` | dsh-usage | 一级设置分区 settings.section id `dsh-usage`(创意工坊下方);`[data-dsh-plugin="usage"]` |
|
|
148
158
|
| `model-capabilities` | dsh-model-capabilities | Models 页 `settings.models.provider-card` keyed 槽 key `llm-pi-ai`(提供方卡片扩展区)+ `settings.models.footer` 槽 entry id `ui-model-capabilities`(存档区);`[data-dsh-plugin="model-capabilities"]` |
|
|
149
159
|
| `preset-center` | dsh-preset-center | 创意工坊卡片的「预设」标签页面板(`dsh-workshop.panel` keyed 槽 key `preset`);`[data-dsh-plugin="preset-center"]` |
|
|
160
|
+
| `liangshen` | dsh-liangshen | 首页输入框内的梁神模式拨杆;`[data-dsh-plugin="liangshen"][data-dsh-part="lever"]`,slot entry id `liangshen-lever` |
|
|
150
161
|
|
|
151
162
|
## 已知脆弱点(上游主题缝 PR 诉求)
|
|
152
163
|
|
package/lib/client.js
CHANGED
|
@@ -401,6 +401,16 @@ window.__ModuleLoader__.load({
|
|
|
401
401
|
].join(", ");
|
|
402
402
|
const sourceSets = /* @__PURE__ */ new WeakMap();
|
|
403
403
|
const contentObservers = /* @__PURE__ */ new WeakMap();
|
|
404
|
+
const contentFrames = /* @__PURE__ */ new WeakMap();
|
|
405
|
+
/** Write a marker attribute only when the desired state is not applied yet. */
|
|
406
|
+
function applyMarker(el, attr, active) {
|
|
407
|
+
if (el === null) return;
|
|
408
|
+
if (active) {
|
|
409
|
+
if (el.getAttribute(attr) !== "true") el.setAttribute(attr, "true");
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (el.hasAttribute(attr)) el.removeAttribute(attr);
|
|
413
|
+
}
|
|
404
414
|
/**
|
|
405
415
|
* Report one source's backdrop-art presence. The marker stays on while any
|
|
406
416
|
* source is active, so the skin and wallpaper controllers never clobber each
|
|
@@ -418,16 +428,13 @@ window.__ModuleLoader__.load({
|
|
|
418
428
|
}
|
|
419
429
|
/** Reflect the source set onto html/body and ensure the neutralizer on use. */
|
|
420
430
|
function syncMarker(doc, sources) {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
431
|
+
const active = sources.size > 0;
|
|
432
|
+
applyMarker(doc.body, BACKDROP_ACTIVE_ATTR, active);
|
|
433
|
+
applyMarker(doc.documentElement, BACKDROP_ACTIVE_ATTR, active);
|
|
434
|
+
if (active) {
|
|
424
435
|
ensureSceneNeutralizer(doc);
|
|
425
436
|
startContentObserver(doc);
|
|
426
|
-
} else
|
|
427
|
-
doc.body?.removeAttribute(BACKDROP_ACTIVE_ATTR);
|
|
428
|
-
doc.documentElement?.removeAttribute(BACKDROP_ACTIVE_ATTR);
|
|
429
|
-
stopContentObserver(doc);
|
|
430
|
-
}
|
|
437
|
+
} else stopContentObserver(doc);
|
|
431
438
|
}
|
|
432
439
|
/**
|
|
433
440
|
* Track whether the active conversation scrollport has message rows for the
|
|
@@ -436,13 +443,27 @@ window.__ModuleLoader__.load({
|
|
|
436
443
|
* those stale rows and flash the composer frost over the new empty topic.
|
|
437
444
|
*/
|
|
438
445
|
function updateConversationContent(doc) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
446
|
+
const has = doc.body !== null && doc.body.querySelector(ACTIVE_CONVERSATION_CONTENT_SELECTOR) !== null;
|
|
447
|
+
applyMarker(doc.body, CONVERSATION_CONTENT_ATTR, has);
|
|
448
|
+
applyMarker(doc.documentElement, CONVERSATION_CONTENT_ATTR, has);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Coalesce the mutation bursts of a streaming conversation into one content
|
|
452
|
+
* check per frame; a check scheduled for a document that stopped observing is
|
|
453
|
+
* dropped so a late frame can never re-add the marker after teardown.
|
|
454
|
+
*/
|
|
455
|
+
function scheduleConversationContent(doc) {
|
|
456
|
+
if (contentFrames.has(doc)) return;
|
|
457
|
+
const win = doc.defaultView;
|
|
458
|
+
if (win === null || typeof win.requestAnimationFrame !== "function") {
|
|
459
|
+
updateConversationContent(doc);
|
|
460
|
+
return;
|
|
445
461
|
}
|
|
462
|
+
contentFrames.set(doc, win.requestAnimationFrame(() => {
|
|
463
|
+
contentFrames.delete(doc);
|
|
464
|
+
if (!contentObservers.has(doc)) return;
|
|
465
|
+
updateConversationContent(doc);
|
|
466
|
+
}));
|
|
446
467
|
}
|
|
447
468
|
/** Observe the conversation tree while a backdrop is visible. */
|
|
448
469
|
function startContentObserver(doc) {
|
|
@@ -450,22 +471,28 @@ window.__ModuleLoader__.load({
|
|
|
450
471
|
updateConversationContent(doc);
|
|
451
472
|
const win = doc.defaultView;
|
|
452
473
|
if (win === null || typeof win.MutationObserver !== "function") return;
|
|
453
|
-
const observer = new win.MutationObserver(() =>
|
|
474
|
+
const observer = new win.MutationObserver(() => scheduleConversationContent(doc));
|
|
454
475
|
observer.observe(doc.body ?? doc.documentElement, {
|
|
455
476
|
childList: true,
|
|
456
477
|
subtree: true
|
|
457
478
|
});
|
|
458
479
|
contentObservers.set(doc, observer);
|
|
459
480
|
}
|
|
460
|
-
/** Stop the content observer and drop the
|
|
481
|
+
/** Stop the content observer, cancel pending work and drop the marker. */
|
|
461
482
|
function stopContentObserver(doc) {
|
|
483
|
+
const frame = contentFrames.get(doc);
|
|
484
|
+
if (frame !== void 0) {
|
|
485
|
+
const win = doc.defaultView;
|
|
486
|
+
if (win !== null && typeof win.cancelAnimationFrame === "function") win.cancelAnimationFrame(frame);
|
|
487
|
+
contentFrames.delete(doc);
|
|
488
|
+
}
|
|
462
489
|
const observer = contentObservers.get(doc);
|
|
463
490
|
if (observer !== void 0) {
|
|
464
491
|
observer.disconnect();
|
|
465
492
|
contentObservers.delete(doc);
|
|
466
493
|
}
|
|
467
|
-
doc.body
|
|
468
|
-
doc.documentElement
|
|
494
|
+
applyMarker(doc.body, CONVERSATION_CONTENT_ATTR, false);
|
|
495
|
+
applyMarker(doc.documentElement, CONVERSATION_CONTENT_ATTR, false);
|
|
469
496
|
}
|
|
470
497
|
/**
|
|
471
498
|
* Install the shared composer-seat neutralizer, keyed by head presence so a
|
|
@@ -2320,11 +2347,13 @@ window.__ModuleLoader__.load({
|
|
|
2320
2347
|
const blurContent = (0, react.useSyncExternalStore)(background.subscribe, background.blurContent);
|
|
2321
2348
|
const inputCardBlur = (0, react.useSyncExternalStore)(background.subscribe, background.inputCardBlur);
|
|
2322
2349
|
const bubbleOpacity = (0, react.useSyncExternalStore)(background.subscribe, background.bubbleOpacity);
|
|
2350
|
+
const bubbleBlur = (0, react.useSyncExternalStore)(background.subscribe, background.bubbleBlur);
|
|
2323
2351
|
const [shownOpacity, setShownOpacity] = useLiveValue(opacity);
|
|
2324
2352
|
const [shownBlurEmpty, setShownBlurEmpty] = useLiveValue(blurEmpty);
|
|
2325
2353
|
const [shownBlurContent, setShownBlurContent] = useLiveValue(blurContent);
|
|
2326
2354
|
const [shownInputCardBlur, setShownInputCardBlur] = useLiveValue(inputCardBlur);
|
|
2327
2355
|
const [shownBubbleOpacity, setShownBubbleOpacity] = useLiveValue(bubbleOpacity);
|
|
2356
|
+
const [shownBubbleBlur, setShownBubbleBlur] = useLiveValue(bubbleBlur);
|
|
2328
2357
|
const catalog = (0, react.useSyncExternalStore)(runtime.subscribe, runtime.catalog);
|
|
2329
2358
|
const state = (0, react.useSyncExternalStore)(runtime.subscribe, runtime.controller.getState);
|
|
2330
2359
|
const customThemeState = (0, react.useSyncExternalStore)(customTheme.subscribe, customTheme.getState);
|
|
@@ -2816,6 +2845,40 @@ window.__ModuleLoader__.load({
|
|
|
2816
2845
|
})
|
|
2817
2846
|
]
|
|
2818
2847
|
}),
|
|
2848
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2849
|
+
className: skin_center_module_css_default.backgroundRow,
|
|
2850
|
+
children: [
|
|
2851
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2852
|
+
className: skin_center_module_css_default.backgroundHead,
|
|
2853
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2854
|
+
className: skin_center_module_css_default.backgroundLabel,
|
|
2855
|
+
children: t("bubbleBlur")
|
|
2856
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2857
|
+
className: skin_center_module_css_default.backgroundValue,
|
|
2858
|
+
"aria-hidden": "true",
|
|
2859
|
+
children: [shownBubbleBlur, "px"]
|
|
2860
|
+
})]
|
|
2861
|
+
}),
|
|
2862
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SliderControl, {
|
|
2863
|
+
id: "skin-center-bubble-blur",
|
|
2864
|
+
className: skin_center_module_css_default.backgroundRange,
|
|
2865
|
+
min: 0,
|
|
2866
|
+
max: 20,
|
|
2867
|
+
step: 1,
|
|
2868
|
+
value: bubbleBlur,
|
|
2869
|
+
ariaValuetext: shownBubbleBlur + "px",
|
|
2870
|
+
ariaLabel: t("bubbleBlur"),
|
|
2871
|
+
onChanging: setShownBubbleBlur,
|
|
2872
|
+
onChange: (value) => {
|
|
2873
|
+
background.setBubbleBlur(value);
|
|
2874
|
+
}
|
|
2875
|
+
}),
|
|
2876
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2877
|
+
className: skin_center_module_css_default.backgroundHint,
|
|
2878
|
+
children: t("bubbleBlurHint")
|
|
2879
|
+
})
|
|
2880
|
+
]
|
|
2881
|
+
}),
|
|
2819
2882
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WallpaperPanel, {
|
|
2820
2883
|
t,
|
|
2821
2884
|
wallpaper
|
|
@@ -2973,7 +3036,8 @@ window.__ModuleLoader__.load({
|
|
|
2973
3036
|
backgroundBlurEmpty: 0,
|
|
2974
3037
|
backgroundBlurContent: 0,
|
|
2975
3038
|
inputCardBlur: 10,
|
|
2976
|
-
bubbleOpacity: 50
|
|
3039
|
+
bubbleOpacity: 50,
|
|
3040
|
+
bubbleBlur: 10
|
|
2977
3041
|
};
|
|
2978
3042
|
/** The fields normalize/sanitize know about; unknown keys are dropped. */
|
|
2979
3043
|
const SKIN_BACKGROUND_FIELDS = Object.keys(SKIN_BACKGROUND_DEFAULTS);
|
|
@@ -2985,7 +3049,8 @@ window.__ModuleLoader__.load({
|
|
|
2985
3049
|
backgroundBlurEmpty: [0, 20],
|
|
2986
3050
|
backgroundBlurContent: [0, 20],
|
|
2987
3051
|
inputCardBlur: [0, 20],
|
|
2988
|
-
bubbleOpacity: [0, 100]
|
|
3052
|
+
bubbleOpacity: [0, 100],
|
|
3053
|
+
bubbleBlur: [0, 20]
|
|
2989
3054
|
};
|
|
2990
3055
|
function isRecord$1(value) {
|
|
2991
3056
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -3053,10 +3118,13 @@ window.__ModuleLoader__.load({
|
|
|
3053
3118
|
const SCRIM_VAR = "--dsw-skin-scrim";
|
|
3054
3119
|
/** CSS custom property consumed by skins that expose translucent bubbles. */
|
|
3055
3120
|
const BUBBLE_ALPHA_VAR = "--dsh-skin-bubble-alpha";
|
|
3121
|
+
/** CSS custom property consumed by skins that expose a bubble backdrop blur. */
|
|
3122
|
+
const BUBBLE_BLUR_VAR = "--dsh-skin-bubble-blur";
|
|
3056
3123
|
/** CSS custom property consumed by the shared composer neutralizer. */
|
|
3057
3124
|
const INPUT_CARD_BLUR_VAR = "--dsh-input-card-blur";
|
|
3058
3125
|
SKIN_BACKGROUND_DEFAULTS.backgroundOpacity;
|
|
3059
3126
|
SKIN_BACKGROUND_DEFAULTS.bubbleOpacity;
|
|
3127
|
+
SKIN_BACKGROUND_DEFAULTS.bubbleBlur;
|
|
3060
3128
|
SKIN_BACKGROUND_DEFAULTS.backgroundBlurEmpty;
|
|
3061
3129
|
/**
|
|
3062
3130
|
* Selector for a conversation message row inside the shell's center column.
|
|
@@ -3084,6 +3152,7 @@ window.__ModuleLoader__.load({
|
|
|
3084
3152
|
blurContentValue = SKIN_BACKGROUND_DEFAULTS.backgroundBlurContent;
|
|
3085
3153
|
inputCardBlurValue = SKIN_BACKGROUND_DEFAULTS.inputCardBlur;
|
|
3086
3154
|
bubbleOpacityValue = SKIN_BACKGROUND_DEFAULTS.bubbleOpacity;
|
|
3155
|
+
bubbleBlurValue = SKIN_BACKGROUND_DEFAULTS.bubbleBlur;
|
|
3087
3156
|
listeners = /* @__PURE__ */ new Set();
|
|
3088
3157
|
persist;
|
|
3089
3158
|
/** The fixed backdrop-filter element, present only while active blur > 0. */
|
|
@@ -3105,6 +3174,7 @@ window.__ModuleLoader__.load({
|
|
|
3105
3174
|
this.applyOcclusion();
|
|
3106
3175
|
this.applyInputCardBlur();
|
|
3107
3176
|
this.applyBubbleOpacity();
|
|
3177
|
+
this.applyBubbleBlur();
|
|
3108
3178
|
this.syncBlur();
|
|
3109
3179
|
}
|
|
3110
3180
|
/**
|
|
@@ -3119,6 +3189,7 @@ window.__ModuleLoader__.load({
|
|
|
3119
3189
|
this.applyOcclusion();
|
|
3120
3190
|
this.applyInputCardBlur();
|
|
3121
3191
|
this.applyBubbleOpacity();
|
|
3192
|
+
this.applyBubbleBlur();
|
|
3122
3193
|
this.syncBlur();
|
|
3123
3194
|
this.publish();
|
|
3124
3195
|
}
|
|
@@ -3130,7 +3201,8 @@ window.__ModuleLoader__.load({
|
|
|
3130
3201
|
backgroundBlurEmpty: this.blurEmptyValue,
|
|
3131
3202
|
backgroundBlurContent: this.blurContentValue,
|
|
3132
3203
|
inputCardBlur: this.inputCardBlurValue,
|
|
3133
|
-
bubbleOpacity: this.bubbleOpacityValue
|
|
3204
|
+
bubbleOpacity: this.bubbleOpacityValue,
|
|
3205
|
+
bubbleBlur: this.bubbleBlurValue
|
|
3134
3206
|
};
|
|
3135
3207
|
}
|
|
3136
3208
|
enabled = () => this.enabledValue;
|
|
@@ -3139,6 +3211,7 @@ window.__ModuleLoader__.load({
|
|
|
3139
3211
|
this.applyOcclusion();
|
|
3140
3212
|
this.applyInputCardBlur();
|
|
3141
3213
|
this.applyBubbleOpacity();
|
|
3214
|
+
this.applyBubbleBlur();
|
|
3142
3215
|
this.syncBlur();
|
|
3143
3216
|
this.publish();
|
|
3144
3217
|
this.persist(this.snapshot());
|
|
@@ -3148,6 +3221,7 @@ window.__ModuleLoader__.load({
|
|
|
3148
3221
|
blurContent = () => this.blurContentValue;
|
|
3149
3222
|
inputCardBlur = () => this.inputCardBlurValue;
|
|
3150
3223
|
bubbleOpacity = () => this.bubbleOpacityValue;
|
|
3224
|
+
bubbleBlur = () => this.bubbleBlurValue;
|
|
3151
3225
|
subscribe = (listener) => {
|
|
3152
3226
|
this.listeners.add(listener);
|
|
3153
3227
|
return () => {
|
|
@@ -3186,6 +3260,12 @@ window.__ModuleLoader__.load({
|
|
|
3186
3260
|
this.publish();
|
|
3187
3261
|
this.persist(this.snapshot());
|
|
3188
3262
|
}
|
|
3263
|
+
setBubbleBlur(value) {
|
|
3264
|
+
this.bubbleBlurValue = this.clampBlur(value);
|
|
3265
|
+
this.applyBubbleBlur();
|
|
3266
|
+
this.publish();
|
|
3267
|
+
this.persist(this.snapshot());
|
|
3268
|
+
}
|
|
3189
3269
|
dispose() {
|
|
3190
3270
|
this.disposed = true;
|
|
3191
3271
|
if (this.rafId !== null) {
|
|
@@ -3195,6 +3275,7 @@ window.__ModuleLoader__.load({
|
|
|
3195
3275
|
this.removeBlurElement();
|
|
3196
3276
|
document.body.style.removeProperty(INPUT_CARD_BLUR_VAR);
|
|
3197
3277
|
document.body.style.removeProperty(BUBBLE_ALPHA_VAR);
|
|
3278
|
+
document.body.style.removeProperty(BUBBLE_BLUR_VAR);
|
|
3198
3279
|
if (this.observer !== null) {
|
|
3199
3280
|
this.observer.disconnect();
|
|
3200
3281
|
this.observer = null;
|
|
@@ -3209,6 +3290,7 @@ window.__ModuleLoader__.load({
|
|
|
3209
3290
|
this.blurContentValue = resolved.backgroundBlurContent;
|
|
3210
3291
|
this.inputCardBlurValue = resolved.inputCardBlur;
|
|
3211
3292
|
this.bubbleOpacityValue = resolved.bubbleOpacity;
|
|
3293
|
+
this.bubbleBlurValue = resolved.bubbleBlur;
|
|
3212
3294
|
}
|
|
3213
3295
|
clampBlur(value) {
|
|
3214
3296
|
return Math.max(0, Math.min(20, Math.round(value)));
|
|
@@ -3230,6 +3312,13 @@ window.__ModuleLoader__.load({
|
|
|
3230
3312
|
}
|
|
3231
3313
|
document.body.style.setProperty(BUBBLE_ALPHA_VAR, String(this.bubbleOpacityValue / 100));
|
|
3232
3314
|
}
|
|
3315
|
+
applyBubbleBlur() {
|
|
3316
|
+
if (!this.enabledValue) {
|
|
3317
|
+
document.body.style.removeProperty(BUBBLE_BLUR_VAR);
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3320
|
+
document.body.style.setProperty(BUBBLE_BLUR_VAR, this.bubbleBlurValue + "px");
|
|
3321
|
+
}
|
|
3233
3322
|
/** Write the current occlusion onto the body CSS variable (0..1 alpha). */
|
|
3234
3323
|
applyOcclusion() {
|
|
3235
3324
|
if (!this.enabledValue) {
|
|
@@ -3462,6 +3551,8 @@ window.__ModuleLoader__.load({
|
|
|
3462
3551
|
inputCardBlurHint: "Blurs only the area behind the input card while backdrop art is visible; it does not blur the entire wallpaper.",
|
|
3463
3552
|
bubbleOpacity: "Bubble opacity",
|
|
3464
3553
|
bubbleOpacityHint: "Controls translucent message bubbles for skins that expose bubble alpha, such as Whale Mom.",
|
|
3554
|
+
bubbleBlur: "Bubble blur",
|
|
3555
|
+
bubbleBlurHint: "Blurs the backdrop behind translucent message bubbles; independent of bubble opacity, 0 disables.",
|
|
3465
3556
|
backgroundBlurHint: "Applies a separate Gaussian blur to the backdrop for the empty conversation and the conversation with content; 0 disables.",
|
|
3466
3557
|
backgroundBlurInert: "Visible only with skins that paint a backdrop; the official default has none.",
|
|
3467
3558
|
backgroundHint: "Instantly veils the backdrop behind the panels — higher values obscure the art to help you focus.",
|
|
@@ -3582,6 +3673,8 @@ window.__ModuleLoader__.load({
|
|
|
3582
3673
|
inputCardBlurHint: "仅模糊输入卡背后的区域,不会让整张壁纸变糊。",
|
|
3583
3674
|
bubbleOpacity: "气泡不透明度",
|
|
3584
3675
|
bubbleOpacityHint: "调节支持气泡 alpha 的皮肤消息气泡,例如鲸鱼妈妈。",
|
|
3676
|
+
bubbleBlur: "气泡模糊程度",
|
|
3677
|
+
bubbleBlurHint: "模糊半透明消息气泡背后的区域,与「气泡不透明度」相互独立,0 为关闭。",
|
|
3585
3678
|
backgroundBlurHint: "对话为空与有内容时分别应用不同的背景高斯模糊强度,0 为关闭。",
|
|
3586
3679
|
backgroundBlurInert: "仅对带背景图插画的皮肤可见;官方默认无背景图。",
|
|
3587
3680
|
backgroundHint: "即时为面板背后的背景加遮罩——数值越高越能弱化插画,帮你集中注意力。",
|
|
@@ -4056,9 +4149,12 @@ window.__ModuleLoader__.load({
|
|
|
4056
4149
|
/* #1117: The upstream recommended badge pairs two background-fill tokens
|
|
4057
4150
|
as bg + text — in dark mode, skins like Blue Fantasy collapse them to
|
|
4058
4151
|
near-identical dark navy values (contrast ~1:1). Override the text
|
|
4059
|
-
color to a readable foreground and tweak the background for contrast.
|
|
4060
|
-
|
|
4061
|
-
|
|
4152
|
+
color to a readable foreground and tweak the background for contrast.
|
|
4153
|
+
The dark-theme attribute lives on <body>, so it belongs inside the
|
|
4154
|
+
scoped selector: prefixing the already-scoped list produced
|
|
4155
|
+
"body ... html ...", a descendant chain that can never match (#1490). */
|
|
4156
|
+
${scoped("body[data-ds-dark-theme] [data-question-key] [class*=\"_badge\"]")},
|
|
4157
|
+
${scoped("body[data-ds-dark-theme] [data-question-scroll] [class*=\"_badge\"]")} {
|
|
4062
4158
|
color: var(--dsw-alias-label-primary, #ffffff) !important;
|
|
4063
4159
|
background: var(--dsw-alias-interactive-bg-active, color-mix(in srgb, var(--dsw-alias-button-info-fill, #4a5fa8) 50%, transparent)) !important;
|
|
4064
4160
|
}
|
|
@@ -4076,35 +4172,62 @@ window.__ModuleLoader__.load({
|
|
|
4076
4172
|
try {
|
|
4077
4173
|
win?.scrollTo?.(0, 0);
|
|
4078
4174
|
} catch {}
|
|
4175
|
+
const composerSelector = COMPOSER_SEAT_SELECTORS.join(", ");
|
|
4079
4176
|
let resizeObserver = null;
|
|
4080
4177
|
let mutationObserver = null;
|
|
4081
4178
|
let observedComposer = null;
|
|
4179
|
+
let appliedHeight = "";
|
|
4180
|
+
let scheduledFrame = null;
|
|
4181
|
+
let disposed = false;
|
|
4182
|
+
const resolveComposer = () => {
|
|
4183
|
+
if (observedComposer !== null && observedComposer.isConnected) return observedComposer;
|
|
4184
|
+
return doc.body === null ? null : doc.body.querySelector(composerSelector);
|
|
4185
|
+
};
|
|
4082
4186
|
const syncHeight = () => {
|
|
4083
4187
|
if (doc.body === null) return;
|
|
4084
|
-
const composer =
|
|
4085
|
-
if (composer
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
}
|
|
4091
|
-
const rect = composer.getBoundingClientRect();
|
|
4092
|
-
if (rect.height > 0) doc.documentElement?.style.setProperty("--dsh-composer-height", `${Math.ceil(rect.height)}px`);
|
|
4188
|
+
const composer = resolveComposer();
|
|
4189
|
+
if (composer === null) return;
|
|
4190
|
+
if (observedComposer !== composer) {
|
|
4191
|
+
if (observedComposer !== null && resizeObserver !== null) resizeObserver.unobserve(observedComposer);
|
|
4192
|
+
observedComposer = composer;
|
|
4193
|
+
if (resizeObserver !== null) resizeObserver.observe(composer);
|
|
4093
4194
|
}
|
|
4195
|
+
const rect = composer.getBoundingClientRect();
|
|
4196
|
+
if (rect.height <= 0) return;
|
|
4197
|
+
const root = doc.documentElement;
|
|
4198
|
+
const next = `${Math.ceil(rect.height)}px`;
|
|
4199
|
+
if (next === appliedHeight || root === null) return;
|
|
4200
|
+
appliedHeight = next;
|
|
4201
|
+
root.style.setProperty("--dsh-composer-height", next);
|
|
4202
|
+
};
|
|
4203
|
+
const scheduleSync = () => {
|
|
4204
|
+
if (scheduledFrame !== null || disposed) return;
|
|
4205
|
+
if (win === null || typeof win.requestAnimationFrame !== "function") {
|
|
4206
|
+
syncHeight();
|
|
4207
|
+
return;
|
|
4208
|
+
}
|
|
4209
|
+
scheduledFrame = win.requestAnimationFrame(() => {
|
|
4210
|
+
scheduledFrame = null;
|
|
4211
|
+
if (disposed) return;
|
|
4212
|
+
syncHeight();
|
|
4213
|
+
});
|
|
4094
4214
|
};
|
|
4095
4215
|
if (win !== null && typeof win.ResizeObserver === "function") resizeObserver = new win.ResizeObserver(() => syncHeight());
|
|
4096
4216
|
if (win !== null && typeof win.MutationObserver === "function" && doc.body !== null) {
|
|
4097
|
-
mutationObserver = new win.MutationObserver(() =>
|
|
4217
|
+
mutationObserver = new win.MutationObserver(() => scheduleSync());
|
|
4098
4218
|
mutationObserver.observe(doc.body, {
|
|
4099
4219
|
childList: true,
|
|
4100
4220
|
subtree: true
|
|
4101
4221
|
});
|
|
4102
4222
|
}
|
|
4103
4223
|
syncHeight();
|
|
4104
|
-
let disposed = false;
|
|
4105
4224
|
return () => {
|
|
4106
4225
|
if (disposed) return;
|
|
4107
4226
|
disposed = true;
|
|
4227
|
+
if (scheduledFrame !== null) {
|
|
4228
|
+
if (win !== null && typeof win.cancelAnimationFrame === "function") win.cancelAnimationFrame(scheduledFrame);
|
|
4229
|
+
scheduledFrame = null;
|
|
4230
|
+
}
|
|
4108
4231
|
if (resizeObserver !== null) {
|
|
4109
4232
|
resizeObserver.disconnect();
|
|
4110
4233
|
resizeObserver = null;
|
|
@@ -4114,6 +4237,7 @@ window.__ModuleLoader__.load({
|
|
|
4114
4237
|
mutationObserver = null;
|
|
4115
4238
|
}
|
|
4116
4239
|
observedComposer = null;
|
|
4240
|
+
appliedHeight = "";
|
|
4117
4241
|
doc.documentElement?.style.removeProperty("--dsh-composer-height");
|
|
4118
4242
|
style.remove();
|
|
4119
4243
|
};
|
|
@@ -4322,22 +4446,28 @@ window.__ModuleLoader__.load({
|
|
|
4322
4446
|
function setBackgroundLayer(activation, nodes) {
|
|
4323
4447
|
const style = doc.body.style;
|
|
4324
4448
|
const previousBackgroundColor = style.getPropertyValue("background-color");
|
|
4449
|
+
const previousBackgroundImage = style.getPropertyValue("background-image");
|
|
4325
4450
|
const restore = () => {
|
|
4326
4451
|
if (currentActivation !== activation) return;
|
|
4327
4452
|
clearLayer(layers.background);
|
|
4328
4453
|
setSceneBackdropActive(doc, "skin", false);
|
|
4329
4454
|
if (previousBackgroundColor === "") style.removeProperty("background-color");
|
|
4330
4455
|
else style.setProperty("background-color", previousBackgroundColor);
|
|
4456
|
+
if (previousBackgroundImage === "") style.removeProperty("background-image");
|
|
4457
|
+
else style.setProperty("background-image", previousBackgroundImage);
|
|
4331
4458
|
};
|
|
4332
4459
|
clearLayer(layers.background);
|
|
4333
4460
|
if (nodes.length > 0) {
|
|
4334
4461
|
for (const node of nodes) layers.background.appendChild(node);
|
|
4335
4462
|
style.setProperty("background-color", "transparent");
|
|
4463
|
+
style.setProperty("background-image", "none");
|
|
4336
4464
|
setSceneBackdropActive(doc, "skin", true);
|
|
4337
4465
|
} else {
|
|
4338
4466
|
setSceneBackdropActive(doc, "skin", false);
|
|
4339
4467
|
if (previousBackgroundColor === "") style.removeProperty("background-color");
|
|
4340
4468
|
else style.setProperty("background-color", previousBackgroundColor);
|
|
4469
|
+
if (previousBackgroundImage === "") style.removeProperty("background-image");
|
|
4470
|
+
else style.setProperty("background-image", previousBackgroundImage);
|
|
4341
4471
|
}
|
|
4342
4472
|
ledger.record(activation, "background:layer", restore);
|
|
4343
4473
|
}
|
|
@@ -5011,7 +5141,7 @@ window.__ModuleLoader__.load({
|
|
|
5011
5141
|
/** The building package's version, when the bundle carries it. */
|
|
5012
5142
|
function bakedVersion() {
|
|
5013
5143
|
try {
|
|
5014
|
-
return "0.3.
|
|
5144
|
+
return "0.3.22";
|
|
5015
5145
|
} catch {
|
|
5016
5146
|
return;
|
|
5017
5147
|
}
|
|
@@ -5224,12 +5354,14 @@ window.__ModuleLoader__.load({
|
|
|
5224
5354
|
blurContent: () => background.blurContent(),
|
|
5225
5355
|
inputCardBlur: () => background.inputCardBlur(),
|
|
5226
5356
|
bubbleOpacity: () => background.bubbleOpacity(),
|
|
5357
|
+
bubbleBlur: () => background.bubbleBlur(),
|
|
5227
5358
|
subscribe: (listener) => background.subscribe(listener),
|
|
5228
5359
|
set: (opacity) => background.set(opacity),
|
|
5229
5360
|
setBlurEmpty: (value) => background.setBlurEmpty(value),
|
|
5230
5361
|
setBlurContent: (value) => background.setBlurContent(value),
|
|
5231
5362
|
setInputCardBlur: (value) => background.setInputCardBlur(value),
|
|
5232
5363
|
setBubbleOpacity: (value) => background.setBubbleOpacity(value),
|
|
5364
|
+
setBubbleBlur: (value) => background.setBubbleBlur(value),
|
|
5233
5365
|
dispose: () => background.dispose()
|
|
5234
5366
|
},
|
|
5235
5367
|
wallpaper: {
|