dsh-deepseek-style-theme 1.43.1 → 1.43.4
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.md +17 -2
- package/cordis.patch.yml +6 -6
- package/lib/client.js +337 -41
- package/lib/index.js +874 -824
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,13 +112,28 @@ dsh plugin --profile web add ./releases/dsh-deepseek-style-theme-1.43.1.tgz
|
|
|
112
112
|
|
|
113
113
|
### 从 npm
|
|
114
114
|
|
|
115
|
+
> ⚠️ **暂时不要用这一条。** npm 上的 `latest` 仍是 **1.43.1**,而那一版带着一个致命缺陷:客户端 bundle 的注册 id 还是旧 scope 的 `@dsh-external/dsh-deepseek-style-theme`,而宿主按包名 `dsh-deepseek-style-theme` 要求它自我注册,于是 **bundle 加载成功却什么都没注册**,主题的整个客户端半边失效。1.43.3 已修复。
|
|
116
|
+
>
|
|
117
|
+
> 在 1.43.3 发到 npm 之前,请用上面的 **tgz 别名地址** 或 `github:` 安装。
|
|
118
|
+
|
|
115
119
|
```bash
|
|
120
|
+
# 修复版发到 npm 之后可用;在那之前用 tgz 别名地址
|
|
116
121
|
dsh plugin --profile web add dsh-deepseek-style-theme
|
|
117
122
|
```
|
|
118
123
|
|
|
119
|
-
> 包名是**无 scope** 的 `dsh-deepseek-style-theme`。这是刻意的:`@dsh-external` 这个 scope 在 npm 上属于别人(`wulei1107`,下面挂着 `@dsh-external/dsh-vision-toolkit
|
|
124
|
+
> 包名是**无 scope** 的 `dsh-deepseek-style-theme`。这是刻意的:`@dsh-external` 这个 scope 在 npm 上属于别人(`wulei1107`,下面挂着 `@dsh-external/dsh-vision-toolkit`),不是本项目的命名空间,也发不进去。
|
|
125
|
+
>
|
|
126
|
+
> **改名的三个引用点必须同时对齐**,缺一个都会静默失效,且失效方式各不相同:
|
|
127
|
+
>
|
|
128
|
+
> | 位置 | 不对齐的后果 |
|
|
129
|
+
> |---|---|
|
|
130
|
+
> | `package.json` 的 `name` | 包装不进去 / 目录名不符 |
|
|
131
|
+
> | `cordis.patch.yml` 的 `name:` | Loader 解析不到模块,**插件装配失败** |
|
|
132
|
+
> | `lib/client.js` 里 `__ModuleLoader__.load` 的 `id` | bundle 加载成功却什么都没注册,**客户端半边失效**(1.43.1 的缺陷) |
|
|
133
|
+
>
|
|
134
|
+
> 自查:`grep '@dsh-external' lib/` 应当**一处都不命中**;命中即漏改(有意保留的兼容位置除外)。
|
|
120
135
|
>
|
|
121
|
-
> npm 是最省事的安装源:不走 `git clone`(绕开代理/证书问题),也不依赖 GitHub Release 资产(绕开 `releases/latest` 那类 URL
|
|
136
|
+
> npm 是最省事的安装源:不走 `git clone`(绕开代理/证书问题),也不依赖 GitHub Release 资产(绕开 `releases/latest` 那类 URL 腐烂)。
|
|
122
137
|
|
|
123
138
|
```bash
|
|
124
139
|
# 或任意 git 仓库地址(若该仓库未提交构建产物,
|
package/cordis.patch.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# DeepSeek-Style-Theme bundle patch: inserts its public dsh.client entry into
|
|
2
|
-
# the web plugin roster. The bundle is the official dsh plugin shape — install
|
|
3
|
-
# it with `dsh plugin --profile <name> add <path-or-git-url>`.
|
|
4
|
-
- insert:
|
|
5
|
-
- id: ui-skin-deepseek-style
|
|
6
|
-
name: 'dsh-deepseek-style-theme'
|
|
1
|
+
# DeepSeek-Style-Theme bundle patch: inserts its public dsh.client entry into
|
|
2
|
+
# the web plugin roster. The bundle is the official dsh plugin shape — install
|
|
3
|
+
# it with `dsh plugin --profile <name> add <path-or-git-url>`.
|
|
4
|
+
- insert:
|
|
5
|
+
- id: ui-skin-deepseek-style
|
|
6
|
+
name: 'dsh-deepseek-style-theme'
|
package/lib/client.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// The loader requires this bundle to register itself under the id the host asked
|
|
2
|
+
// for, and that id is the package NAME of whichever copy is installed -- which is
|
|
3
|
+
// not one value during a rename. The package moved from
|
|
4
|
+
// @dsh-external/dsh-deepseek-style-theme to the unscoped dsh-deepseek-style-theme
|
|
5
|
+
// in 1.43.1, so a profile installed before the rename asks for the old id and one
|
|
6
|
+
// installed after asks for the new one. A single hard-coded literal therefore
|
|
7
|
+
// breaks whichever half it does not match, and BOTH directions were hit for real,
|
|
8
|
+
// one machine each:
|
|
9
|
+
//
|
|
10
|
+
// literal old, install new -> "loaded without registering \"dsh-deepseek-style-theme\""
|
|
11
|
+
// literal new, install old -> "loaded without registering \"@dsh-external/...\""
|
|
12
|
+
//
|
|
13
|
+
// So register under BOTH ids with the same factory: the loader finds the one it
|
|
14
|
+
// wants and the other entry is simply never asked for. The registrations are
|
|
15
|
+
// guarded individually because a loader might reject an id it did not request,
|
|
16
|
+
// and that must not take the working one down with it.
|
|
17
|
+
const dshDeepseekStyleThemeFactory = (require) => {
|
|
18
|
+
var module = { exports: {} };
|
|
19
|
+
var exports = module.exports;
|
|
6
20
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
21
|
const React = require("react");
|
|
8
22
|
|
|
@@ -26,7 +40,7 @@ window.__ModuleLoader__.load({
|
|
|
26
40
|
// page data — session titles, file paths, workspace names — must go
|
|
27
41
|
// through `textContent`/`title`/`setAttribute`, never `innerHTML`. An
|
|
28
42
|
// interpolated value there would be DOM XSS.
|
|
29
|
-
const PLUGIN_ID = "
|
|
43
|
+
const PLUGIN_ID = "dsh-deepseek-style-theme";
|
|
30
44
|
|
|
31
45
|
// ─── fluid background + liquid-glass refraction ───────────────────────
|
|
32
46
|
// Ported from dsh-theme-mineradio v2.3.8 (MIT, Copyright (c) 2026 John Wu).
|
|
@@ -632,7 +646,40 @@ void main() {
|
|
|
632
646
|
var TALL_FILTER_ID = "dshome-glass-dispersion-tall";
|
|
633
647
|
var TALL_TINT_ID = "dshome-glass-dispersion-tall-tint";
|
|
634
648
|
var TALL_REFRACT_ID = "dshome-glass-dispersion-tall-refract";
|
|
635
|
-
|
|
649
|
+
// Two composer filters: `narrow` (an 8px band) and `wide` (16px).
|
|
650
|
+
//
|
|
651
|
+
// The band is sized by what the user can actually SEE, which is the top and
|
|
652
|
+
// bottom edges: the card's top abuts the 任务 bar and its bottom abuts the
|
|
653
|
+
// status line, so displacing the backdrop across those hard edges shows,
|
|
654
|
+
// while left and right sit over a continuous background where the same
|
|
655
|
+
// displacement changes nothing. The user accepted that asymmetry ("允许左右
|
|
656
|
+
// 无反射"), so these maps are tuned for the VERTICAL band and the horizontal
|
|
657
|
+
// one is left wherever it lands.
|
|
658
|
+
//
|
|
659
|
+
// Vertical band on screen = (edge + softness) / mapHeight * 1.56 * cardHeight
|
|
660
|
+
// -- the filter region is 156% of the surface's height (see filterMarkup) --
|
|
661
|
+
// so at the upstream 400x92 aspect and a 112px-tall card that is 1.90x the
|
|
662
|
+
// map inset: 1.7 + 2.5 gives 8px, 3.4 + 5 gives 16px.
|
|
663
|
+
var COMPOSER_FILTER_ID = "dshome-glass-dispersion-composer";
|
|
664
|
+
var COMPOSER_TINT_ID = "dshome-glass-dispersion-composer-tint";
|
|
665
|
+
var COMPOSER_REFRACT_ID = "dshome-glass-dispersion-composer-refract";
|
|
666
|
+
var WIDE_FILTER_ID = "dshome-glass-dispersion-composer-wide";
|
|
667
|
+
var WIDE_TINT_ID = "dshome-glass-dispersion-composer-wide-tint";
|
|
668
|
+
var WIDE_REFRACT_ID = "dshome-glass-dispersion-composer-wide-refract";
|
|
669
|
+
var COMPOSER_MAP_W = 400;
|
|
670
|
+
var COMPOSER_MAP_H = 92;
|
|
671
|
+
var COMPOSER_MAP_RADIUS = 50;
|
|
672
|
+
var COMPOSER_MAP_EDGE = 1.7;
|
|
673
|
+
var COMPOSER_MAP_SOFTNESS = 2.5;
|
|
674
|
+
var COMPOSER_WIDE_EDGE = 3.4;
|
|
675
|
+
var COMPOSER_WIDE_SOFTNESS = 5;
|
|
676
|
+
// Chromatic aberration, composer filters only. 0.18 splits the base
|
|
677
|
+
// displacement into three: red at 118%, blue at 82%, green in the middle,
|
|
678
|
+
// which is what makes a lens edge fringe instead of merely tinting. Kept to
|
|
679
|
+
// the two composer filters because it triples the displacement passes, and
|
|
680
|
+
// because the shared filters have to keep upstream's exact shape for the
|
|
681
|
+
// frosted recipe.
|
|
682
|
+
var COMPOSER_ABERRATION = 0.18;
|
|
636
683
|
var DEFAULT_REF_SCALE = 60;
|
|
637
684
|
// The liquid recipe drives the same feDisplacementMap harder: at 60 the
|
|
638
685
|
// bend is there but only just legible once the blur sits on top of it, and
|
|
@@ -644,15 +691,20 @@ void main() {
|
|
|
644
691
|
var TINT_SAT = 0.85;
|
|
645
692
|
var TINT_LIGHT = 0.6;
|
|
646
693
|
var DEFAULT_TINT_HUE = 44;
|
|
647
|
-
|
|
694
|
+
// Upstream derives the inset from the map's SHORT side (7% of it, halved),
|
|
695
|
+
// which is only uniform if the map is square. The composer passes `edge`
|
|
696
|
+
// instead: one absolute inset for both axes, which comes out uniform as
|
|
697
|
+
// long as the map's aspect matches the filter region's (see COMPOSER_MAP_*).
|
|
698
|
+
// Defaults reproduce upstream's numbers exactly, so the frosted recipe's
|
|
699
|
+
// map stays byte for byte what it was.
|
|
700
|
+
function buildDisplacementMapDataUrl(width = 400, height = 92, radius = 50, edge = null, softness = 11) {
|
|
648
701
|
const w = Math.max(240, Math.round(width));
|
|
649
702
|
const h = Math.max(48, Math.round(height));
|
|
650
703
|
const r = Math.max(12, Math.round(radius));
|
|
651
|
-
const
|
|
652
|
-
const
|
|
653
|
-
const
|
|
654
|
-
const
|
|
655
|
-
const svg2 = `<svg viewBox="0 0 ${w} ${h}" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="glass-x" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#000"/><stop offset="100%" stop-color="#f00"/></linearGradient><linearGradient id="glass-y" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#000"/><stop offset="100%" stop-color="#00f"/></linearGradient></defs><rect x="0" y="0" width="${w}" height="${h}" fill="#000"/><rect x="0" y="0" width="${w}" height="${h}" rx="${r}" fill="url(#glass-x)"/><rect x="0" y="0" width="${w}" height="${h}" rx="${r}" fill="url(#glass-y)" style="mix-blend-mode:screen"/><rect x="${edge.toFixed(2)}" y="${edge.toFixed(2)}" width="${innerW.toFixed(2)}" height="${innerH.toFixed(2)}" rx="${r}" fill="hsl(0 0% 50% / 1)" style="filter:blur(11px)"/></svg>`;
|
|
704
|
+
const inset = edge === null ? Math.min(w, h) * 0.035 : Math.max(0, edge);
|
|
705
|
+
const innerW = Math.max(1, w - inset * 2);
|
|
706
|
+
const innerH = Math.max(1, h - inset * 2);
|
|
707
|
+
const svg2 = `<svg viewBox="0 0 ${w} ${h}" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="glass-x" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#000"/><stop offset="100%" stop-color="#f00"/></linearGradient><linearGradient id="glass-y" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#000"/><stop offset="100%" stop-color="#00f"/></linearGradient></defs><rect x="0" y="0" width="${w}" height="${h}" fill="#000"/><rect x="0" y="0" width="${w}" height="${h}" rx="${r}" fill="url(#glass-x)"/><rect x="0" y="0" width="${w}" height="${h}" rx="${r}" fill="url(#glass-y)" style="mix-blend-mode:screen"/><rect x="${inset.toFixed(2)}" y="${inset.toFixed(2)}" width="${innerW.toFixed(2)}" height="${innerH.toFixed(2)}" rx="${r}" fill="hsl(0 0% 50% / 1)" style="filter:blur(${softness})"/></svg>`;
|
|
656
708
|
return `data:image/svg+xml,${encodeURIComponent(svg2)}`;
|
|
657
709
|
}
|
|
658
710
|
// Inlined from upstream `src/client/glass-dispersion.ts` (line 2409) —
|
|
@@ -693,8 +745,29 @@ void main() {
|
|
|
693
745
|
}
|
|
694
746
|
// Inlined from upstream `src/client/glass-dispersion.ts` (line 2443) —
|
|
695
747
|
// builds the wide/tall SVG <filter> pair startGlassDispersion injects.
|
|
696
|
-
|
|
697
|
-
|
|
748
|
+
//
|
|
749
|
+
// `aberration` (0 = off, upstream's shape byte for byte) adds true
|
|
750
|
+
// chromatic aberration: the backdrop is displaced TWICE MORE at slightly
|
|
751
|
+
// different scales, and the result is assembled channel by channel -- R
|
|
752
|
+
// from the stronger displacement, B from the weaker, G from the base. That
|
|
753
|
+
// is what puts a red/blue fringe on a real lens edge; the tinted
|
|
754
|
+
// difference-blend below is only a colour wash and does not separate
|
|
755
|
+
// channels at all.
|
|
756
|
+
//
|
|
757
|
+
// The two extra maps carry a data-aberration factor so setRefraction() can
|
|
758
|
+
// rescale them in step with the base one instead of flattening all three
|
|
759
|
+
// to the same value.
|
|
760
|
+
function filterMarkup(id, refractId, tintId, map, aberration = 0) {
|
|
761
|
+
const chromatic = aberration <= 0 ? '' :
|
|
762
|
+
`<feDisplacementMap data-aberration="${(1 + aberration).toFixed(3)}" in="SourceGraphic" in2="map" scale="${DEFAULT_REF_SCALE}" xChannelSelector="R" yChannelSelector="B" result="refractR"></feDisplacementMap>` +
|
|
763
|
+
`<feDisplacementMap data-aberration="${(1 - aberration).toFixed(3)}" in="SourceGraphic" in2="map" scale="${DEFAULT_REF_SCALE}" xChannelSelector="R" yChannelSelector="B" result="refractB"></feDisplacementMap>` +
|
|
764
|
+
`<feColorMatrix in="refracted" type="matrix" values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0" result="onlyG"></feColorMatrix>` +
|
|
765
|
+
`<feColorMatrix in="refractR" type="matrix" values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" result="onlyR"></feColorMatrix>` +
|
|
766
|
+
`<feColorMatrix in="refractB" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0" result="onlyB"></feColorMatrix>` +
|
|
767
|
+
`<feBlend in="onlyG" in2="onlyR" mode="screen" result="rgMerge"></feBlend>` +
|
|
768
|
+
`<feBlend in="rgMerge" in2="onlyB" mode="screen" result="aberrated"></feBlend>`;
|
|
769
|
+
const merged = chromatic === '' ? 'refracted' : 'aberrated';
|
|
770
|
+
return `<filter id="${id}" color-interpolation-filters="sRGB" x="-12%" y="-28%" width="124%" height="156%"><feImage href="${map}" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none" result="map"></feImage><feDisplacementMap id="${refractId}" in="SourceGraphic" in2="map" scale="${DEFAULT_REF_SCALE}" xChannelSelector="R" yChannelSelector="B" result="refracted"></feDisplacementMap>${chromatic}<feOffset in="${merged}" dx="${EDGE_DX}" dy="0" result="shifted"></feOffset><feBlend in="shifted" in2="${merged}" mode="difference" result="edgeDiff"></feBlend><feColorMatrix id="${tintId}" in="edgeDiff" type="matrix" values="${tintMatrix(DEFAULT_TINT_HUE, TINT_OPACITY)}" result="edgeTint"></feColorMatrix><feBlend in="${merged}" in2="edgeTint" mode="screen" result="output"></feBlend><feGaussianBlur in="output" stdDeviation="0.5"></feGaussianBlur></filter>`;
|
|
698
771
|
}
|
|
699
772
|
/**
|
|
700
773
|
* Mount the two SVG backdrop filters and set `ATTR` on <html> so the
|
|
@@ -721,7 +794,9 @@ void main() {
|
|
|
721
794
|
}
|
|
722
795
|
const mapWide = buildDisplacementMapDataUrl(400, 92, 50);
|
|
723
796
|
const mapTall = buildDisplacementMapDataUrl(92, 400, 50);
|
|
724
|
-
const
|
|
797
|
+
const mapComposer = buildDisplacementMapDataUrl(COMPOSER_MAP_W, COMPOSER_MAP_H, COMPOSER_MAP_RADIUS, COMPOSER_MAP_EDGE, COMPOSER_MAP_SOFTNESS);
|
|
798
|
+
const mapComposerWide = buildDisplacementMapDataUrl(COMPOSER_MAP_W, COMPOSER_MAP_H, COMPOSER_MAP_RADIUS, COMPOSER_WIDE_EDGE, COMPOSER_WIDE_SOFTNESS);
|
|
799
|
+
const markup = `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" width="0" height="0" style="position:absolute;overflow:hidden"><defs>` + filterMarkup(FILTER_ID, REFRACT_ID, TINT_ID, mapWide) + filterMarkup(TALL_FILTER_ID, TALL_REFRACT_ID, TALL_TINT_ID, mapTall) + filterMarkup(COMPOSER_FILTER_ID, COMPOSER_REFRACT_ID, COMPOSER_TINT_ID, mapComposer, COMPOSER_ABERRATION) + filterMarkup(WIDE_FILTER_ID, WIDE_REFRACT_ID, WIDE_TINT_ID, mapComposerWide, COMPOSER_ABERRATION) + `</defs></svg>`;
|
|
725
800
|
const container = document.createElement("div");
|
|
726
801
|
container.setAttribute("aria-hidden", "true");
|
|
727
802
|
container.style.cssText = "position:absolute;width:0;height:0;overflow:hidden;";
|
|
@@ -736,8 +811,15 @@ void main() {
|
|
|
736
811
|
tint.forEach((node) => node.setAttribute("values", values));
|
|
737
812
|
},
|
|
738
813
|
setRefraction(scale) {
|
|
739
|
-
|
|
740
|
-
|
|
814
|
+
// The aberration maps are the same displacement at a slightly
|
|
815
|
+
// different scale, so they carry a factor and are rescaled in step;
|
|
816
|
+
// flattening them all to one value would erase the fringing.
|
|
817
|
+
const base = Math.max(0, Math.min(140, Number(scale) || 0));
|
|
818
|
+
refract.forEach((node) => {
|
|
819
|
+
const factor = Number(node.getAttribute("data-aberration"));
|
|
820
|
+
const value = Number.isFinite(factor) && factor > 0 ? base * factor : base;
|
|
821
|
+
node.setAttribute("scale", String(Math.max(0, Math.min(140, value))));
|
|
822
|
+
});
|
|
741
823
|
},
|
|
742
824
|
dispose() {
|
|
743
825
|
root.removeAttribute(ATTR);
|
|
@@ -1343,7 +1425,15 @@ html[data-dshome-dispersion] .VOzbGW_panel{
|
|
|
1343
1425
|
// agent is already working is `"steering"`. Measured on the current build,
|
|
1344
1426
|
// a transcript can contain ONLY steering bubbles — anchoring the selector
|
|
1345
1427
|
// on "user" alone silently skipped every bubble on the page.
|
|
1346
|
-
|
|
1428
|
+
//
|
|
1429
|
+
// The second half covers the gap the user hit: a message typed while the
|
|
1430
|
+
// agent is still working is painted in the transcript BEFORE it is picked
|
|
1431
|
+
// up, and at that moment it sits outside any flow-kind container, so the
|
|
1432
|
+
// two anchored selectors miss it and it renders unglazed until the turn
|
|
1433
|
+
// consumes it. Rather than enumerate the container it lands in, this side
|
|
1434
|
+
// takes any bubble that is NOT part of an assistant step — which is the
|
|
1435
|
+
// only place a bubble must not be glassed.
|
|
1436
|
+
const LIQUID_BUBBLE = ':is([data-chat-flow-kind="user"],[data-chat-flow-kind="steering"]) [class*="bubble" i],[class*="bubble" i]:not([data-chat-flow-kind="assistant-step"] *)';
|
|
1347
1437
|
const LIQUID_CSS = `
|
|
1348
1438
|
@property --dshome-liquid-sweep{syntax:"<angle>";inherits:false;initial-value:0deg}
|
|
1349
1439
|
@keyframes dshome-liquid-sweep{from{--dshome-liquid-sweep:0deg}to{--dshome-liquid-sweep:360deg}}
|
|
@@ -1362,6 +1452,13 @@ html[data-dshome-glass="liquid"]{
|
|
|
1362
1452
|
than everything else on purpose: at the shared 11px the flow behind it stays
|
|
1363
1453
|
legible and the pane never separates from the transcript. */
|
|
1364
1454
|
--dshome-liquid-blur-sidebar:24px;
|
|
1455
|
+
/* The composer blurs less than the rest on purpose. Filters in a backdrop
|
|
1456
|
+
chain apply left to right, so url(refract) followed by blur(N) blurs the
|
|
1457
|
+
refraction AFTER it happens: a band narrower than about the blur radius is
|
|
1458
|
+
simply erased. At 11px the purpose-built ~4px band was invisible, which is
|
|
1459
|
+
exactly what was reported. 8px lets a ~10px band read while still frosting
|
|
1460
|
+
the backdrop. */
|
|
1461
|
+
--dshome-liquid-blur-composer:8px;
|
|
1365
1462
|
/* One extra veil on top of the sidebar's glass. The pane sits over the fluid
|
|
1366
1463
|
at roughly the same tone as the conversation it borders, so without this
|
|
1367
1464
|
lift the two read as one surface. It is white in light mode. */
|
|
@@ -1424,6 +1521,25 @@ html[data-dshome-glass="liquid"] [data-composer-card]::after{
|
|
|
1424
1521
|
background-image:none!important;
|
|
1425
1522
|
box-shadow:none!important;
|
|
1426
1523
|
}
|
|
1524
|
+
/* The frosted recipe gives the composer a brand-tinted conic ring, painted by
|
|
1525
|
+
the patch block at inset:-1px and spun by dsh-border-spin. Under liquid the
|
|
1526
|
+
user asked for it to go: it sits one pixel OUTSIDE the card's own 1.5px white
|
|
1527
|
+
border, so the pair reads as a coloured line with a white line outside it, and
|
|
1528
|
+
two competing edges is what liquid glass is not. content:none removes the
|
|
1529
|
+
pseudo-element outright rather than painting it transparent. */
|
|
1530
|
+
html[data-dshome-glass="liquid"] body [data-composer-card]::before{
|
|
1531
|
+
content:none!important;
|
|
1532
|
+
background:none!important;
|
|
1533
|
+
animation:none!important;
|
|
1534
|
+
}
|
|
1535
|
+
/* With the ring gone the card's own 1.5px white border is the only edge left,
|
|
1536
|
+
and on its own it reads as a flat white outline rather than as glass — which
|
|
1537
|
+
is what the user saw next. Liquid's edge is the inset hairline plus the
|
|
1538
|
+
refraction, so the border goes transparent. The WIDTH stays: removing it
|
|
1539
|
+
would resize the box and shift every control inside by 3px. */
|
|
1540
|
+
html[data-dshome-glass="liquid"] body [data-composer-card]{
|
|
1541
|
+
border-color:transparent!important;
|
|
1542
|
+
}
|
|
1427
1543
|
/* The sidebar pane carries its own fill and its own shape: rounded only on the
|
|
1428
1544
|
edge that faces the conversation, so it reads as a panel clipped to the
|
|
1429
1545
|
window rather than as a full-bleed column. The hairline ring in the shared
|
|
@@ -1462,9 +1578,14 @@ html[data-dshome-glass="liquid"] body .hHd-Xa_root::after{
|
|
|
1462
1578
|
}
|
|
1463
1579
|
/* The travelling edge highlight. mask-composite:exclude turns the filled
|
|
1464
1580
|
conic gradient into a 1px perimeter band; padding:1px on the pseudo-element
|
|
1465
|
-
sets that band's width without touching the product's box model.
|
|
1466
|
-
|
|
1467
|
-
|
|
1581
|
+
sets that band's width without touching the product's box model.
|
|
1582
|
+
It is drawn on the SIDEBAR ONLY. The user asked for it off the composer and
|
|
1583
|
+
off the message bubbles under liquid: on a small pill the band reads as a
|
|
1584
|
+
bright white outline rather than as light travelling a glass edge, and on the
|
|
1585
|
+
composer it doubled up with the card's own border. The bubbles and the
|
|
1586
|
+
composer keep liquid's other three marks — the translucent fill, the sheen
|
|
1587
|
+
and the refraction. */
|
|
1588
|
+
html[data-dshome-glass="liquid"] .hHd-Xa_root::after{
|
|
1468
1589
|
content:"";position:absolute;inset:0;z-index:2;pointer-events:none;border-radius:inherit;
|
|
1469
1590
|
padding:1px;
|
|
1470
1591
|
background:conic-gradient(from var(--dshome-liquid-sweep),
|
|
@@ -1477,12 +1598,31 @@ html[data-dshome-glass="liquid"] ${LIQUID_BUBBLE}::after{
|
|
|
1477
1598
|
mask-composite:exclude;
|
|
1478
1599
|
animation:dshome-liquid-sweep 6.5s linear infinite;
|
|
1479
1600
|
}
|
|
1480
|
-
|
|
1601
|
+
/* The composer's edge refraction. Three states, selected by the durable
|
|
1602
|
+
composerRefraction setting (see html[data-dshome-composer]):
|
|
1603
|
+
narrow (default) -- an 8px band top and bottom
|
|
1604
|
+
wide -- a 16px band top and bottom
|
|
1605
|
+
off -- no dispersion at all
|
|
1606
|
+
Left and right are left as they fall: the band is there, but over a
|
|
1607
|
+
continuous background a horizontal displacement has nothing to show, which
|
|
1608
|
+
the user accepted. */
|
|
1481
1609
|
html[data-dshome-dispersion][data-dshome-glass="liquid"] body .wSkVaW_header:hover::before,
|
|
1482
1610
|
html[data-dshome-dispersion][data-dshome-glass="liquid"] body ${LIQUID_BUBBLE}{
|
|
1483
1611
|
-webkit-backdrop-filter:url(#dshome-glass-dispersion) blur(var(--dshome-liquid-blur)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1484
1612
|
backdrop-filter:url(#dshome-glass-dispersion) blur(var(--dshome-liquid-blur)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1485
1613
|
}
|
|
1614
|
+
html[data-dshome-dispersion][data-dshome-glass="liquid"][data-dshome-composer="narrow"] body [data-composer-card]{
|
|
1615
|
+
-webkit-backdrop-filter:url(#dshome-glass-dispersion-composer) blur(var(--dshome-liquid-blur-composer)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1616
|
+
backdrop-filter:url(#dshome-glass-dispersion-composer) blur(var(--dshome-liquid-blur-composer)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1617
|
+
}
|
|
1618
|
+
html[data-dshome-dispersion][data-dshome-glass="liquid"][data-dshome-composer="wide"] body [data-composer-card]{
|
|
1619
|
+
-webkit-backdrop-filter:url(#dshome-glass-dispersion-composer-wide) blur(var(--dshome-liquid-blur-composer)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1620
|
+
backdrop-filter:url(#dshome-glass-dispersion-composer-wide) blur(var(--dshome-liquid-blur-composer)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1621
|
+
}
|
|
1622
|
+
html[data-dshome-dispersion][data-dshome-glass="liquid"][data-dshome-composer="off"] body [data-composer-card]{
|
|
1623
|
+
-webkit-backdrop-filter:blur(var(--dshome-liquid-blur-composer)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1624
|
+
backdrop-filter:blur(var(--dshome-liquid-blur-composer)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1625
|
+
}
|
|
1486
1626
|
/* The workspace list is faded out at its bottom by a gradient whose end stop is
|
|
1487
1627
|
the sidebar-fill token — an OPAQUE colour matched to the product's own sidebar
|
|
1488
1628
|
background. Over a translucent glass pane that stop no longer matches what is
|
|
@@ -1503,9 +1643,20 @@ html[data-dshome-dispersion][data-dshome-glass="liquid"] body .hHd-Xa_root::befo
|
|
|
1503
1643
|
-webkit-backdrop-filter:url(#dshome-glass-dispersion) blur(var(--dshome-liquid-blur-sidebar)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1504
1644
|
backdrop-filter:url(#dshome-glass-dispersion) blur(var(--dshome-liquid-blur-sidebar)) saturate(var(--dshome-liquid-saturate))!important;
|
|
1505
1645
|
}
|
|
1646
|
+
/* Backdrop blur, switched off by the durable backdropBlur setting. Each glass
|
|
1647
|
+
recipe reads its radius from a variable, so turning the frosting off is one
|
|
1648
|
+
0px per variable -- the translucency, the sheen and the edge refraction all
|
|
1649
|
+
stay exactly as they were. Written with a body step so it also out-ranks the
|
|
1650
|
+
html[data-dshome-glass] block the liquid radii are declared in. */
|
|
1651
|
+
html[data-dshome-blur="off"],
|
|
1652
|
+
html[data-dshome-blur="off"] body{
|
|
1653
|
+
--dshome-glass-blur:0px;
|
|
1654
|
+
--dshome-liquid-blur:0px;
|
|
1655
|
+
--dshome-liquid-blur-sidebar:0px;
|
|
1656
|
+
--dshome-liquid-blur-composer:0px;
|
|
1657
|
+
}
|
|
1506
1658
|
@media (prefers-reduced-motion:reduce){
|
|
1507
|
-
html[data-dshome-glass="liquid"] .hHd-Xa_root::after
|
|
1508
|
-
html[data-dshome-glass="liquid"] ${LIQUID_BUBBLE}::after{
|
|
1659
|
+
html[data-dshome-glass="liquid"] .hHd-Xa_root::after{
|
|
1509
1660
|
animation:none;
|
|
1510
1661
|
}
|
|
1511
1662
|
}
|
|
@@ -1577,12 +1728,17 @@ html[data-dshome-dispersion][data-dshome-glass="liquid"] body .hHd-Xa_root::befo
|
|
|
1577
1728
|
function createDarkSync(ctx, theme) {
|
|
1578
1729
|
const apply = () => {
|
|
1579
1730
|
let dark = false;
|
|
1580
|
-
//
|
|
1581
|
-
//
|
|
1582
|
-
//
|
|
1583
|
-
//
|
|
1584
|
-
|
|
1585
|
-
|
|
1731
|
+
// Two signals, and BOTH of them lie in some state -- measured, not
|
|
1732
|
+
// assumed:
|
|
1733
|
+
// * the theme service reported `light` while the page was in dark
|
|
1734
|
+
// mode, so treating it as the only source painted a dark page light;
|
|
1735
|
+
// * `data-ds-dark-theme` was still on <body> after a switch back to
|
|
1736
|
+
// light, so treating IT as authoritative painted a light page dark.
|
|
1737
|
+
// This is the precedence that shipped through 1.43.1 and behaved in both
|
|
1738
|
+
// modes: ask the service first, and let the product's own attribute
|
|
1739
|
+
// override a "not dark" answer. Keep it, and sanity-check the signal
|
|
1740
|
+
// before touching it again.
|
|
1741
|
+
if (theme !== undefined && theme !== null && typeof theme.getTheme === 'function') {
|
|
1586
1742
|
try {
|
|
1587
1743
|
const snap = theme.getTheme();
|
|
1588
1744
|
dark = snap !== undefined && snap !== null &&
|
|
@@ -1592,6 +1748,7 @@ html[data-dshome-dispersion][data-dshome-glass="liquid"] body .hHd-Xa_root::befo
|
|
|
1592
1748
|
dark = false;
|
|
1593
1749
|
}
|
|
1594
1750
|
}
|
|
1751
|
+
if (!dark) dark = document.body.hasAttribute('data-ds-dark-theme');
|
|
1595
1752
|
if (dark) document.body.setAttribute('data-dshome-dark', '');
|
|
1596
1753
|
else document.body.removeAttribute('data-dshome-dark');
|
|
1597
1754
|
};
|
|
@@ -1629,12 +1786,16 @@ html[data-dshome-dispersion][data-dshome-glass="liquid"] body .hHd-Xa_root::befo
|
|
|
1629
1786
|
const root = document.documentElement;
|
|
1630
1787
|
const apply = () => {
|
|
1631
1788
|
root.setAttribute('data-dshome-glass', dsttGetGlass());
|
|
1789
|
+
root.setAttribute('data-dshome-composer', dsttGetComposer());
|
|
1790
|
+
root.setAttribute('data-dshome-blur', dsttGetBlur() ? 'on' : 'off');
|
|
1632
1791
|
};
|
|
1633
1792
|
apply();
|
|
1634
1793
|
const unsubscribe = dsttSubscribe(apply);
|
|
1635
1794
|
return () => {
|
|
1636
1795
|
unsubscribe();
|
|
1637
1796
|
root.removeAttribute('data-dshome-glass');
|
|
1797
|
+
root.removeAttribute('data-dshome-composer');
|
|
1798
|
+
root.removeAttribute('data-dshome-blur');
|
|
1638
1799
|
};
|
|
1639
1800
|
}
|
|
1640
1801
|
|
|
@@ -3258,6 +3419,18 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3258
3419
|
liquid: { zh: "液态", en: "Liquid" },
|
|
3259
3420
|
frosted: { zh: "白磨砂", en: "Frosted" }
|
|
3260
3421
|
};
|
|
3422
|
+
// How wide the composer's edge refraction is under liquid, measured on the
|
|
3423
|
+
// top and bottom edges -- the only two where a displacement has anything to
|
|
3424
|
+
// show. The stylesheet gates the three states on <html data-dshome-composer>.
|
|
3425
|
+
// `origin` was this option's first id and is still accepted from a settings
|
|
3426
|
+
// file written before the rename; it reads back as `wide`.
|
|
3427
|
+
const DSTT_COMPOSER = ["narrow", "wide", "off"];
|
|
3428
|
+
const DSTT_COMPOSER_DEFAULT = "narrow";
|
|
3429
|
+
const DSTT_COMPOSER_LABELS = {
|
|
3430
|
+
narrow: { zh: "窄 8px", en: "Narrow 8px" },
|
|
3431
|
+
wide: { zh: "宽 16px", en: "Wide 16px" },
|
|
3432
|
+
off: { zh: "无", en: "Off" }
|
|
3433
|
+
};
|
|
3261
3434
|
|
|
3262
3435
|
/**
|
|
3263
3436
|
* Shared in-memory mirror of the durable DSTT mode. The settings domain's
|
|
@@ -3265,21 +3438,86 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3265
3438
|
* plugin's own loopback channel instead; every reader (the color driver,
|
|
3266
3439
|
* the settings tab) subscribes to this mirror.
|
|
3267
3440
|
*/
|
|
3268
|
-
const dsttState = { mode: "peakvalley-redblue", fluidBrush: false, glassStyle: DSTT_GLASS_DEFAULT, listeners: new Set() };
|
|
3441
|
+
const dsttState = { mode: "peakvalley-redblue", fluidBrush: false, glassStyle: DSTT_GLASS_DEFAULT, composer: DSTT_COMPOSER_DEFAULT, blur: true, listeners: new Set() };
|
|
3442
|
+
// Fields the user has chosen in this session. A host half that predates a
|
|
3443
|
+
// field ignores it and answers without it -- or with its own default -- so
|
|
3444
|
+
// without this a fresh choice gets overwritten by the next sync and the
|
|
3445
|
+
// option appears to snap straight back to its default.
|
|
3446
|
+
const dsttTouched = new Set();
|
|
3269
3447
|
const dsttGetMode = () => dsttState.mode;
|
|
3270
3448
|
const dsttGetGlass = () => (DSTT_GLASS_STYLES.includes(dsttState.glassStyle) ? dsttState.glassStyle : DSTT_GLASS_DEFAULT);
|
|
3271
|
-
|
|
3449
|
+
const dsttGetComposer = () => {
|
|
3450
|
+
if (dsttState.composer === "origin") return "wide";
|
|
3451
|
+
return DSTT_COMPOSER.includes(dsttState.composer) ? dsttState.composer : DSTT_COMPOSER_DEFAULT;
|
|
3452
|
+
};
|
|
3453
|
+
const dsttGetBlur = () => dsttState.blur !== false;
|
|
3454
|
+
/**
|
|
3455
|
+
* Turn the glass frosting on or off. Same shape as the other CSS-only
|
|
3456
|
+
* preferences: apply locally first, then let the host persist it, and treat
|
|
3457
|
+
* its answer as confirmation only.
|
|
3458
|
+
*/
|
|
3459
|
+
async function dsttSetBlur(ctx, next) {
|
|
3460
|
+
dsttState.blur = next === true;
|
|
3461
|
+
dsttTouched.add("blur");
|
|
3462
|
+
dsttNotify();
|
|
3463
|
+
try {
|
|
3464
|
+
const result = await bridgeCall(DSTT_SET, { mode: dsttState.mode, backdropBlur: dsttState.blur });
|
|
3465
|
+
if (result !== undefined && result !== null && result.ok === true) {
|
|
3466
|
+
return result.value.backdropBlur === dsttState.blur;
|
|
3467
|
+
}
|
|
3468
|
+
} catch (error) {
|
|
3469
|
+
// Fall through: the local choice stands, it just was not stored.
|
|
3470
|
+
}
|
|
3471
|
+
return false;
|
|
3472
|
+
}
|
|
3473
|
+
/**
|
|
3474
|
+
* Persist the composer's refraction width through the bridge.
|
|
3475
|
+
*
|
|
3476
|
+
* Applied locally FIRST, before the round trip. Both this and glassStyle
|
|
3477
|
+
* only flip a CSS attribute, so the choice is fully usable the moment it is
|
|
3478
|
+
* made — and it has to be, because a running dsh keeps the host half it
|
|
3479
|
+
* booted with: until `dsh web` is restarted, `dstt.mode.set` ignores fields
|
|
3480
|
+
* it does not know and answers without them, which used to make a brand new
|
|
3481
|
+
* setting look broken. The cost of applying first is that a choice made
|
|
3482
|
+
* against a stale host is not persisted and reverts on reload, so the
|
|
3483
|
+
* return value still reports the truth.
|
|
3484
|
+
*/
|
|
3485
|
+
async function dsttSetComposer(ctx, next) {
|
|
3486
|
+
if (!DSTT_COMPOSER.includes(next)) return false;
|
|
3487
|
+
dsttState.composer = next;
|
|
3488
|
+
dsttTouched.add("composer");
|
|
3489
|
+
dsttNotify();
|
|
3490
|
+
try {
|
|
3491
|
+
const result = await bridgeCall(DSTT_SET, { mode: dsttState.mode, composerRefraction: next });
|
|
3492
|
+
// The response is used ONLY to confirm. It must never be written back
|
|
3493
|
+
// into the mirror: a host that accepts the call but does not store the
|
|
3494
|
+
// field answers with its own value (the default, `narrow`), and copying
|
|
3495
|
+
// that in is what made the option snap straight back the moment the
|
|
3496
|
+
// round trip landed.
|
|
3497
|
+
if (result !== undefined && result !== null && result.ok === true && DSTT_COMPOSER.includes(result.value.composerRefraction)) {
|
|
3498
|
+
return result.value.composerRefraction === next;
|
|
3499
|
+
}
|
|
3500
|
+
} catch (error) {
|
|
3501
|
+
// Fall through: the local choice stands, it just was not stored.
|
|
3502
|
+
}
|
|
3503
|
+
return false;
|
|
3504
|
+
}
|
|
3505
|
+
/** Persist the glass recipe through the bridge; resolves with success.
|
|
3506
|
+
* Applied locally first for the same reason as dsttSetComposer above. */
|
|
3272
3507
|
async function dsttSetGlass(ctx, next) {
|
|
3273
3508
|
if (!DSTT_GLASS_STYLES.includes(next)) return false;
|
|
3509
|
+
dsttState.glassStyle = next;
|
|
3510
|
+
dsttTouched.add("glassStyle");
|
|
3511
|
+
dsttNotify();
|
|
3274
3512
|
try {
|
|
3275
3513
|
const result = await bridgeCall(DSTT_SET, { mode: dsttState.mode, glassStyle: next });
|
|
3514
|
+
// Confirmation only -- see dsttSetComposer for why the host's echo must
|
|
3515
|
+
// not be copied back into the mirror.
|
|
3276
3516
|
if (result !== undefined && result !== null && result.ok === true && DSTT_GLASS_STYLES.includes(result.value.glassStyle)) {
|
|
3277
|
-
|
|
3278
|
-
dsttNotify();
|
|
3279
|
-
return true;
|
|
3517
|
+
return result.value.glassStyle === next;
|
|
3280
3518
|
}
|
|
3281
3519
|
} catch (error) {
|
|
3282
|
-
// Fall through
|
|
3520
|
+
// Fall through: the local choice stands, it just was not stored.
|
|
3283
3521
|
}
|
|
3284
3522
|
return false;
|
|
3285
3523
|
}
|
|
@@ -3327,6 +3565,9 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3327
3565
|
return await response.json();
|
|
3328
3566
|
}
|
|
3329
3567
|
|
|
3568
|
+
/** Fallback used when the host half is unavailable. */
|
|
3569
|
+
const dsttGetBlurFallback = () => dsttState.blur !== false;
|
|
3570
|
+
|
|
3330
3571
|
/** Pull the durable mode from the host half once. */
|
|
3331
3572
|
async function dsttSync(ctx) {
|
|
3332
3573
|
try {
|
|
@@ -3335,8 +3576,13 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3335
3576
|
dsttState.mode = result.value.mode;
|
|
3336
3577
|
dsttState.fluidBrush = result.value.fluidBrush === true;
|
|
3337
3578
|
// An older host half answers without a glass recipe: keep the
|
|
3338
|
-
// default rather than clearing the attribute to nothing.
|
|
3339
|
-
|
|
3579
|
+
// default rather than clearing the attribute to nothing. And a
|
|
3580
|
+
// field the user has already chosen this session is never taken
|
|
3581
|
+
// back from the host -- a stale host answers with its own default,
|
|
3582
|
+
// which is what made a fresh choice look like it snapped back.
|
|
3583
|
+
if (!dsttTouched.has("glassStyle") && DSTT_GLASS_STYLES.includes(result.value.glassStyle)) dsttState.glassStyle = result.value.glassStyle;
|
|
3584
|
+
if (!dsttTouched.has("composer") && DSTT_COMPOSER.includes(result.value.composerRefraction)) dsttState.composer = result.value.composerRefraction;
|
|
3585
|
+
if (!dsttTouched.has("blur") && typeof result.value.backdropBlur === "boolean") dsttState.blur = result.value.backdropBlur;
|
|
3340
3586
|
dsttNotify();
|
|
3341
3587
|
}
|
|
3342
3588
|
} catch (error) {}
|
|
@@ -3592,6 +3838,16 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3592
3838
|
if (dstt === undefined || typeof dstt.setGlass !== 'function' || next === glassNow) return;
|
|
3593
3839
|
dstt.setGlass(next);
|
|
3594
3840
|
};
|
|
3841
|
+
const composerNow = dstt !== undefined && typeof dstt.composer === 'function' ? dstt.composer() : DSTT_COMPOSER_DEFAULT;
|
|
3842
|
+
const pickComposer = (next) => {
|
|
3843
|
+
if (dstt === undefined || typeof dstt.setComposer !== 'function' || next === composerNow) return;
|
|
3844
|
+
dstt.setComposer(next);
|
|
3845
|
+
};
|
|
3846
|
+
const blurOn = dstt !== undefined && typeof dstt.blur === 'function' ? dstt.blur() !== false : true;
|
|
3847
|
+
const toggleBlur = () => {
|
|
3848
|
+
if (dstt === undefined || typeof dstt.setBlur !== 'function') return;
|
|
3849
|
+
dstt.setBlur(!blurOn);
|
|
3850
|
+
};
|
|
3595
3851
|
|
|
3596
3852
|
return React.createElement('div', { className: 'dshome-dstt' },
|
|
3597
3853
|
React.createElement('h3', null,
|
|
@@ -3643,6 +3899,34 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3643
3899
|
className: 'dshome-dstt-seg-btn' + (glassNow === style ? ' dshome-on' : ''),
|
|
3644
3900
|
onClick: () => pickGlass(style)
|
|
3645
3901
|
}, isZh ? DSTT_GLASS_LABELS[style].zh : DSTT_GLASS_LABELS[style].en)))),
|
|
3902
|
+
React.createElement('div', { className: 'dshome-dstt-row' },
|
|
3903
|
+
React.createElement('div', { className: 'dshome-dstt-row-body' },
|
|
3904
|
+
React.createElement('div', { className: 'dshome-dstt-row-title' }, isZh ? '对话框边缘倒影' : 'Composer edge reflection'),
|
|
3905
|
+
React.createElement('div', { className: 'dshome-dstt-row-hint' }, isZh
|
|
3906
|
+
? '液态下对话框边缘的折射带宽(按上下量——左右背后是连续背景,同样的位移看不出变化)。窄 8px(默认)/ 宽 16px / 无,三者都是专为这张卡片做的位移图。'
|
|
3907
|
+
: 'Width of the lens band at the composer edge under liquid, measured top and bottom — left and right sit over a continuous backdrop where the same displacement shows nothing. Narrow 8px (default) / Wide 16px / Off; each is a map built for this card.')),
|
|
3908
|
+
React.createElement('div', { className: 'dshome-dstt-seg', role: 'radiogroup', 'aria-label': isZh ? '对话框边缘倒影' : 'Composer edge reflection' },
|
|
3909
|
+
DSTT_COMPOSER.map((choice) => React.createElement('button', {
|
|
3910
|
+
key: choice,
|
|
3911
|
+
type: 'button',
|
|
3912
|
+
role: 'radio',
|
|
3913
|
+
'aria-checked': composerNow === choice,
|
|
3914
|
+
className: 'dshome-dstt-seg-btn' + (composerNow === choice ? ' dshome-on' : ''),
|
|
3915
|
+
onClick: () => pickComposer(choice)
|
|
3916
|
+
}, isZh ? DSTT_COMPOSER_LABELS[choice].zh : DSTT_COMPOSER_LABELS[choice].en)))),
|
|
3917
|
+
React.createElement('div', { className: 'dshome-dstt-row' },
|
|
3918
|
+
React.createElement('div', { className: 'dshome-dstt-row-body' },
|
|
3919
|
+
React.createElement('div', { className: 'dshome-dstt-row-title' }, isZh ? '背景模糊(磨砂)' : 'Backdrop blur'),
|
|
3920
|
+
React.createElement('div', { className: 'dshome-dstt-row-hint' }, isZh
|
|
3921
|
+
? '玻璃面板后面那层虚化。关闭后玻璃变成纯半透明:通透度、顶部光泽、边缘折射都保留,只是不再把背后的东西磨掉。'
|
|
3922
|
+
: 'The frosting behind every glass pane. Off leaves the translucency, the sheen and the edge refraction intact and only stops blurring what is behind the glass.')),
|
|
3923
|
+
React.createElement('button', {
|
|
3924
|
+
type: 'button',
|
|
3925
|
+
role: 'switch',
|
|
3926
|
+
'aria-checked': blurOn,
|
|
3927
|
+
className: 'dshome-dstt-seg-btn' + (blurOn ? ' dshome-on' : ''),
|
|
3928
|
+
onClick: toggleBlur
|
|
3929
|
+
}, blurOn ? (isZh ? '已开启' : 'On') : (isZh ? '已关闭' : 'Off'))),
|
|
3646
3930
|
React.createElement('div', { className: 'dshome-dstt-status', 'data-peak': timeSliced && peakNow },
|
|
3647
3931
|
'当前:' + colorName + ' · ' + status));
|
|
3648
3932
|
}
|
|
@@ -3760,6 +4044,10 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3760
4044
|
setBrush: (next) => dsttSetBrush(ctx, next),
|
|
3761
4045
|
glass: dsttGetGlass,
|
|
3762
4046
|
setGlass: (next) => dsttSetGlass(ctx, next),
|
|
4047
|
+
composer: dsttGetComposer,
|
|
4048
|
+
setComposer: (next) => dsttSetComposer(ctx, next),
|
|
4049
|
+
blur: dsttGetBlur,
|
|
4050
|
+
setBlur: (next) => dsttSetBlur(ctx, next),
|
|
3763
4051
|
subscribe: dsttSubscribe
|
|
3764
4052
|
},
|
|
3765
4053
|
locale: ctx.get('locale')
|
|
@@ -3771,5 +4059,13 @@ body[data-dshome-dark] .${CLS}{background:rgba(14,30,60,.94);box-shadow:0 18px 4
|
|
|
3771
4059
|
exports.apply = apply;
|
|
3772
4060
|
exports.inject = ['theme', 'slots', 'locale', 'workspaces', 'connection'];
|
|
3773
4061
|
return module.exports;
|
|
3774
|
-
|
|
3775
|
-
|
|
4062
|
+
};
|
|
4063
|
+
|
|
4064
|
+
// Both ids, same factory. See the note at the top of this file for why one
|
|
4065
|
+
// literal cannot work during the rename.
|
|
4066
|
+
try {
|
|
4067
|
+
window.__ModuleLoader__.load({ id: "dsh-deepseek-style-theme", factory: dshDeepseekStyleThemeFactory });
|
|
4068
|
+
} catch (error) {}
|
|
4069
|
+
try {
|
|
4070
|
+
window.__ModuleLoader__.load({ id: "@dsh-external/dsh-deepseek-style-theme", factory: dshDeepseekStyleThemeFactory });
|
|
4071
|
+
} catch (error) {}
|