dsh-transparent-ui 0.0.0-stage → 1.3.21
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/LICENSE +661 -0
- package/README.md +152 -2
- package/cordis.patch.yml +5 -0
- package/docs/zh.md +153 -0
- package/icon.svg +35 -0
- package/lib/client.js +3201 -0
- package/lib/index.js +6 -0
- package/lib/invariant.js +12 -0
- package/lib/types/aqua-settings.d.ts +16 -0
- package/lib/types/client/AquaPluginCard.d.ts +16 -0
- package/lib/types/client/AquaRow.d.ts +16 -0
- package/lib/types/client/critters.d.ts +18 -0
- package/lib/types/client/fluid-interactions.d.ts +20 -0
- package/lib/types/client/fluid-shader.d.ts +53 -0
- package/lib/types/client/greetings.d.ts +25 -0
- package/lib/types/client/index.d.ts +17 -0
- package/lib/types/client/locales.d.ts +25 -0
- package/lib/types/client/settings-store.d.ts +24 -0
- package/lib/types/client/theme-layer.d.ts +68 -0
- package/lib/types/index.d.ts +10 -0
- package/lib/types/invariant.d.ts +16 -0
- package/package.json +109 -4
package/lib/client.js
ADDED
|
@@ -0,0 +1,3201 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-transparent-ui",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
const module = { exports: {} };
|
|
5
|
+
const exports = module.exports;
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
+
|
|
24
|
+
// src/client/index.ts
|
|
25
|
+
var index_exports = {};
|
|
26
|
+
__export(index_exports, {
|
|
27
|
+
apply: () => apply,
|
|
28
|
+
inject: () => inject
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// src/client/AquaPluginCard.tsx
|
|
33
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
34
|
+
|
|
35
|
+
// src/client/AquaPluginCard.module.css
|
|
36
|
+
var AquaPluginCard_default = { card: "AquaPluginCard_card", head: "AquaPluginCard_head", text: "AquaPluginCard_text", title: "AquaPluginCard_title", description: "AquaPluginCard_description", toggle: "AquaPluginCard_toggle", check: "AquaPluginCard_check" };
|
|
37
|
+
var stdin_default = AquaPluginCard_default;
|
|
38
|
+
var id = "@deepseek-ai/dsh-client-ui-aqua/AquaPluginCard.module.css";
|
|
39
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")) {
|
|
40
|
+
const tag = document.createElement("style");
|
|
41
|
+
tag.dataset.plugin = "dsh-transparent-ui";
|
|
42
|
+
tag.dataset.pluginCss = id;
|
|
43
|
+
tag.textContent = ".AquaPluginCard_card{display:flex;flex-direction:column;padding:16px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-1)}.AquaPluginCard_head{display:flex;align-items:center;justify-content:space-between;gap:16px}.AquaPluginCard_text{display:flex;flex-direction:column;gap:2px;min-width:0}.AquaPluginCard_title{font-size:14px;line-height:22px;font-weight:500;color:var(--dsw-alias-label-primary)}.AquaPluginCard_description{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.AquaPluginCard_toggle{flex:none;display:inline-flex;align-items:center;gap:6px;height:28px;padding:0 10px 0 6px;border:1px solid var(--dsw-alias-border-l2);border-radius:14px;background:transparent;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);cursor:pointer}.AquaPluginCard_toggle:hover{background:var(--dsw-alias-interactive-bg-hover)}.AquaPluginCard_toggle[aria-pressed=true]{border-color:transparent;background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.AquaPluginCard_check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px}\n";
|
|
44
|
+
document.head.appendChild(tag);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/client/AquaPluginCard.tsx
|
|
48
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
49
|
+
function AquaPluginCard(props) {
|
|
50
|
+
const { t, setEnabled, useStore } = props;
|
|
51
|
+
const enabled = useStore((s) => s.enabled);
|
|
52
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: stdin_default.card, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: stdin_default.head, children: [
|
|
53
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: stdin_default.text, children: [
|
|
54
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: stdin_default.title, children: t("aqua.title") }),
|
|
55
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: stdin_default.description, children: t("aqua.description") })
|
|
56
|
+
] }),
|
|
57
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
58
|
+
"button",
|
|
59
|
+
{
|
|
60
|
+
type: "button",
|
|
61
|
+
className: stdin_default.toggle,
|
|
62
|
+
"aria-pressed": enabled,
|
|
63
|
+
onClick: () => {
|
|
64
|
+
setEnabled(!enabled);
|
|
65
|
+
},
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: stdin_default.check, children: enabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 16 }) }),
|
|
68
|
+
enabled ? t("aqua.enable") : t("aqua.disable")
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
] }) });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/client/AquaAppearanceRow.tsx
|
|
76
|
+
var import_react = require("react");
|
|
77
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
78
|
+
|
|
79
|
+
// src/client/AquaAppearanceRow.module.css
|
|
80
|
+
var AquaAppearanceRow_default = { group: "AquaAppearanceRow_group", subGroup: "AquaAppearanceRow_subGroup", subTitle: "AquaAppearanceRow_subTitle", controls: "AquaAppearanceRow_controls", row: "AquaAppearanceRow_row", rowLabel: "AquaAppearanceRow_rowLabel", inlineLabel: "AquaAppearanceRow_inlineLabel", rowHint: "AquaAppearanceRow_rowHint", groupHint: "AquaAppearanceRow_groupHint", knobHint: "AquaAppearanceRow_knobHint", toggle: "AquaAppearanceRow_toggle", toggleOn: "AquaAppearanceRow_toggleOn", check: "AquaAppearanceRow_check", knob: "AquaAppearanceRow_knob", knobLabel: "AquaAppearanceRow_knobLabel", slider: "AquaAppearanceRow_slider", numberWrap: "AquaAppearanceRow_numberWrap", number: "AquaAppearanceRow_number", unit: "AquaAppearanceRow_unit", segmented: "AquaAppearanceRow_segmented", seg: "AquaAppearanceRow_seg", segActive: "AquaAppearanceRow_segActive", wallpaperPick: "AquaAppearanceRow_wallpaperPick", fileInput: "AquaAppearanceRow_fileInput", pickButton: "AquaAppearanceRow_pickButton", deleteButton: "AquaAppearanceRow_deleteButton" };
|
|
81
|
+
var stdin_default2 = AquaAppearanceRow_default;
|
|
82
|
+
var id2 = "@deepseek-ai/dsh-client-ui-aqua/AquaAppearanceRow.module.css";
|
|
83
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]")) {
|
|
84
|
+
const tag = document.createElement("style");
|
|
85
|
+
tag.dataset.plugin = "dsh-transparent-ui";
|
|
86
|
+
tag.dataset.pluginCss = id2;
|
|
87
|
+
tag.textContent = ".AquaAppearanceRow_group{display:flex;flex-direction:column;gap:14px;padding:8px 0 16px;border-bottom:1px solid var(--dsw-alias-border-l2)}.AquaAppearanceRow_subGroup{display:flex;flex-direction:column;gap:8px}.AquaAppearanceRow_subTitle{font-size:13px;line-height:20px;font-weight:600;color:var(--dsw-alias-label-primary)}.AquaAppearanceRow_controls{display:flex;flex-direction:column;gap:10px}.AquaAppearanceRow_row{display:flex;align-items:center;gap:10px}.AquaAppearanceRow_rowLabel{flex:none;width:92px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.AquaAppearanceRow_inlineLabel{flex:none;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.AquaAppearanceRow_rowHint{margin-top:-4px;margin-left:102px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.AquaAppearanceRow_groupHint{margin-top:-4px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.AquaAppearanceRow_knobHint{margin-top:-4px;margin-left:102px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.AquaAppearanceRow_toggle,.AquaAppearanceRow_toggleOn{display:inline-flex;align-items:center;gap:6px;height:28px;padding:0 10px 0 6px;border:1px solid var(--dsw-alias-border-l2);border-radius:14px;background:transparent;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);cursor:pointer}.AquaAppearanceRow_toggle:hover{background:var(--dsw-alias-interactive-bg-hover)}.AquaAppearanceRow_toggleOn{border-color:transparent;background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.AquaAppearanceRow_check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px}.AquaAppearanceRow_knob{display:flex;align-items:center;gap:10px}.AquaAppearanceRow_knobLabel{flex:none;width:92px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.AquaAppearanceRow_slider{flex:1;min-width:0;accent-color:var(--dsw-alias-state-business-primary)}.AquaAppearanceRow_numberWrap{flex:none;display:inline-flex;align-items:center;gap:4px}.AquaAppearanceRow_number{width:56px;height:26px;padding:0 6px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);text-align:right}.AquaAppearanceRow_number::-webkit-outer-spin-button,.AquaAppearanceRow_number::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.AquaAppearanceRow_unit{flex:none;width:18px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.AquaAppearanceRow_segmented{display:inline-flex;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;overflow:hidden}.AquaAppearanceRow_seg,.AquaAppearanceRow_segActive{height:26px;padding:0 12px;border:none;background:transparent;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer}.AquaAppearanceRow_seg+.AquaAppearanceRow_seg,.AquaAppearanceRow_segActive+.AquaAppearanceRow_seg,.AquaAppearanceRow_seg+.AquaAppearanceRow_segActive{border-left:1px solid var(--dsw-alias-border-l2)}.AquaAppearanceRow_segActive{background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.AquaAppearanceRow_wallpaperPick{display:flex;align-items:center;gap:10px}.AquaAppearanceRow_fileInput{display:none}.AquaAppearanceRow_pickButton{height:26px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);cursor:pointer}.AquaAppearanceRow_pickButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.AquaAppearanceRow_deleteButton{height:26px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;font-size:12px;line-height:18px;color:var(--dsw-alias-label-error);cursor:pointer}.AquaAppearanceRow_deleteButton:hover{background:var(--dsw-alias-interactive-bg-hover)}\n";
|
|
88
|
+
document.head.appendChild(tag);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/client/AquaControls.tsx
|
|
92
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
93
|
+
function Knob({ label, value, min, max, step, unit, onChange }) {
|
|
94
|
+
const clamp = (n) => Math.min(max, Math.max(min, Number.isFinite(n) ? n : min));
|
|
95
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: stdin_default2.knob, children: [
|
|
96
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: stdin_default2.knobLabel, children: label }),
|
|
97
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
98
|
+
"input",
|
|
99
|
+
{
|
|
100
|
+
type: "range",
|
|
101
|
+
className: stdin_default2.slider,
|
|
102
|
+
min,
|
|
103
|
+
max,
|
|
104
|
+
step,
|
|
105
|
+
value,
|
|
106
|
+
onChange: (e) => {
|
|
107
|
+
onChange(clamp(Number(e.target.value)));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: stdin_default2.numberWrap, children: [
|
|
112
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
113
|
+
"input",
|
|
114
|
+
{
|
|
115
|
+
type: "number",
|
|
116
|
+
className: stdin_default2.number,
|
|
117
|
+
min,
|
|
118
|
+
max,
|
|
119
|
+
step,
|
|
120
|
+
value,
|
|
121
|
+
onChange: (e) => {
|
|
122
|
+
onChange(clamp(Number(e.target.value)));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
),
|
|
126
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: stdin_default2.unit, children: unit })
|
|
127
|
+
] })
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
function Segmented({ label, value, options, onSelect }) {
|
|
131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: stdin_default2.segmented, role: "group", "aria-label": label, children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
132
|
+
"button",
|
|
133
|
+
{
|
|
134
|
+
type: "button",
|
|
135
|
+
className: option.id === value ? stdin_default2.segActive : stdin_default2.seg,
|
|
136
|
+
"aria-pressed": option.id === value,
|
|
137
|
+
onClick: () => {
|
|
138
|
+
onSelect(option.id);
|
|
139
|
+
},
|
|
140
|
+
children: option.label
|
|
141
|
+
},
|
|
142
|
+
option.id
|
|
143
|
+
)) });
|
|
144
|
+
}
|
|
145
|
+
async function fileToDataUrl(file) {
|
|
146
|
+
const raw = await new Promise((resolve, reject) => {
|
|
147
|
+
const reader = new FileReader();
|
|
148
|
+
reader.onload = () => {
|
|
149
|
+
resolve(String(reader.result));
|
|
150
|
+
};
|
|
151
|
+
reader.onerror = () => {
|
|
152
|
+
reject(reader.error);
|
|
153
|
+
};
|
|
154
|
+
reader.readAsDataURL(file);
|
|
155
|
+
});
|
|
156
|
+
const image = await new Promise((resolve, reject) => {
|
|
157
|
+
const im = new Image();
|
|
158
|
+
im.onload = () => {
|
|
159
|
+
resolve(im);
|
|
160
|
+
};
|
|
161
|
+
im.onerror = () => {
|
|
162
|
+
reject(new Error("image load failed"));
|
|
163
|
+
};
|
|
164
|
+
im.src = raw;
|
|
165
|
+
});
|
|
166
|
+
const scale = Math.min(1, 1920 / Math.max(image.width, image.height));
|
|
167
|
+
const w = Math.max(1, Math.round(image.width * scale));
|
|
168
|
+
const h = Math.max(1, Math.round(image.height * scale));
|
|
169
|
+
const canvas = document.createElement("canvas");
|
|
170
|
+
canvas.width = w;
|
|
171
|
+
canvas.height = h;
|
|
172
|
+
const ctx = canvas.getContext("2d");
|
|
173
|
+
if (ctx === null) return raw;
|
|
174
|
+
ctx.drawImage(image, 0, 0, w, h);
|
|
175
|
+
return canvas.toDataURL("image/jpeg", 0.82);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/client/wallpaper-store.ts
|
|
179
|
+
var DB_NAME = "dsh-aqua-media";
|
|
180
|
+
var STORE = "wallpaper";
|
|
181
|
+
var DB_VERSION = 1;
|
|
182
|
+
var HANDLE_KEY = "videoHandle";
|
|
183
|
+
function openDb() {
|
|
184
|
+
return new Promise((resolve, reject) => {
|
|
185
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
186
|
+
request.onupgradeneeded = () => {
|
|
187
|
+
const db = request.result;
|
|
188
|
+
if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE);
|
|
189
|
+
};
|
|
190
|
+
request.onsuccess = () => {
|
|
191
|
+
resolve(request.result);
|
|
192
|
+
};
|
|
193
|
+
request.onerror = () => {
|
|
194
|
+
reject(request.error ?? new Error("indexedDB open failed"));
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function tx(db, mode) {
|
|
199
|
+
return db.transaction(STORE, mode).objectStore(STORE);
|
|
200
|
+
}
|
|
201
|
+
async function saveVideoBlob(blob) {
|
|
202
|
+
try {
|
|
203
|
+
const db = await openDb();
|
|
204
|
+
const id5 = `v${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
205
|
+
await new Promise((resolve, reject) => {
|
|
206
|
+
const request = tx(db, "readwrite").put(blob, id5);
|
|
207
|
+
request.onsuccess = () => {
|
|
208
|
+
resolve();
|
|
209
|
+
};
|
|
210
|
+
request.onerror = () => {
|
|
211
|
+
reject(request.error ?? new Error("blob put failed"));
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
db.close();
|
|
215
|
+
return `idb:${id5}`;
|
|
216
|
+
} catch {
|
|
217
|
+
return "";
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function loadVideoBlob(id5) {
|
|
221
|
+
try {
|
|
222
|
+
const db = await openDb();
|
|
223
|
+
const blob = await new Promise((resolve, reject) => {
|
|
224
|
+
const request = tx(db, "readonly").get(id5);
|
|
225
|
+
request.onsuccess = () => {
|
|
226
|
+
resolve(request.result);
|
|
227
|
+
};
|
|
228
|
+
request.onerror = () => {
|
|
229
|
+
reject(request.error ?? new Error("blob get failed"));
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
db.close();
|
|
233
|
+
return blob ?? null;
|
|
234
|
+
} catch {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async function deleteVideoBlob(id5) {
|
|
239
|
+
try {
|
|
240
|
+
const db = await openDb();
|
|
241
|
+
await new Promise((resolve) => {
|
|
242
|
+
const request = tx(db, "readwrite").delete(id5);
|
|
243
|
+
request.onsuccess = () => {
|
|
244
|
+
resolve();
|
|
245
|
+
};
|
|
246
|
+
request.onerror = () => {
|
|
247
|
+
resolve();
|
|
248
|
+
};
|
|
249
|
+
});
|
|
250
|
+
db.close();
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async function saveVideoHandle(handle) {
|
|
255
|
+
try {
|
|
256
|
+
const db = await openDb();
|
|
257
|
+
await new Promise((resolve, reject) => {
|
|
258
|
+
const request = tx(db, "readwrite").put(handle, HANDLE_KEY);
|
|
259
|
+
request.onsuccess = () => {
|
|
260
|
+
resolve();
|
|
261
|
+
};
|
|
262
|
+
request.onerror = () => {
|
|
263
|
+
reject(request.error ?? new Error("handle put failed"));
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
db.close();
|
|
267
|
+
return true;
|
|
268
|
+
} catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function loadVideoHandle() {
|
|
273
|
+
try {
|
|
274
|
+
const db = await openDb();
|
|
275
|
+
const handle = await new Promise((resolve, reject) => {
|
|
276
|
+
const request = tx(db, "readonly").get(HANDLE_KEY);
|
|
277
|
+
request.onsuccess = () => {
|
|
278
|
+
resolve(request.result);
|
|
279
|
+
};
|
|
280
|
+
request.onerror = () => {
|
|
281
|
+
reject(request.error ?? new Error("handle get failed"));
|
|
282
|
+
};
|
|
283
|
+
});
|
|
284
|
+
db.close();
|
|
285
|
+
return handle ?? null;
|
|
286
|
+
} catch {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/client/AquaAppearanceRow.tsx
|
|
292
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
293
|
+
function AquaAppearanceRow(props) {
|
|
294
|
+
const {
|
|
295
|
+
t,
|
|
296
|
+
setMode,
|
|
297
|
+
setBlur,
|
|
298
|
+
setFrost,
|
|
299
|
+
setFluidHue,
|
|
300
|
+
setFluidDepth,
|
|
301
|
+
setBgBrightness,
|
|
302
|
+
setBackground,
|
|
303
|
+
setWallpaper,
|
|
304
|
+
setWhale,
|
|
305
|
+
setCritters,
|
|
306
|
+
setMesh,
|
|
307
|
+
setSpotlight,
|
|
308
|
+
setPress,
|
|
309
|
+
setWallpaperBlur,
|
|
310
|
+
setWallpaperFrost,
|
|
311
|
+
setVideoBlur,
|
|
312
|
+
setVideoBrightness,
|
|
313
|
+
authorizeVideo,
|
|
314
|
+
useStore
|
|
315
|
+
} = props;
|
|
316
|
+
const enabled = useStore((s) => s.enabled);
|
|
317
|
+
const mode = useStore((s) => s.mode);
|
|
318
|
+
const blur = useStore((s) => s.blur);
|
|
319
|
+
const frost = useStore((s) => s.frost);
|
|
320
|
+
const fluidHue = useStore((s) => s.fluidHue);
|
|
321
|
+
const fluidDepth = useStore((s) => s.fluidDepth);
|
|
322
|
+
const bgBrightness = useStore((s) => s.bgBrightness);
|
|
323
|
+
const dark = useStore((s) => s.dark);
|
|
324
|
+
const background = useStore((s) => s.background);
|
|
325
|
+
const whale = useStore((s) => s.whale);
|
|
326
|
+
const critters = useStore((s) => s.critters);
|
|
327
|
+
const mesh = useStore((s) => s.mesh);
|
|
328
|
+
const spotlight = useStore((s) => s.spotlight);
|
|
329
|
+
const press = useStore((s) => s.press);
|
|
330
|
+
const wallpaper = useStore((s) => s.wallpaper);
|
|
331
|
+
const wallpaperBlur = useStore((s) => s.wallpaperBlur);
|
|
332
|
+
const wallpaperFrost = useStore((s) => s.wallpaperFrost);
|
|
333
|
+
const videoBlur = useStore((s) => s.videoBlur);
|
|
334
|
+
const videoBrightness = useStore((s) => s.videoBrightness);
|
|
335
|
+
const fileRef = (0, import_react.useRef)(null);
|
|
336
|
+
const videoRef = (0, import_react.useRef)(null);
|
|
337
|
+
const isVideoWallpaper = wallpaper.startsWith("data:video/") || wallpaper.startsWith("idb:") || wallpaper.startsWith("fsa:");
|
|
338
|
+
const pickVideo = () => {
|
|
339
|
+
if (window.showOpenFilePicker !== void 0) {
|
|
340
|
+
void (async () => {
|
|
341
|
+
try {
|
|
342
|
+
const [handle] = await window.showOpenFilePicker({
|
|
343
|
+
multiple: false,
|
|
344
|
+
types: [{ description: "Video", accept: { "video/*": [".mp4", ".webm", ".ogg", ".mov", ".m4v", ".mkv"] } }]
|
|
345
|
+
});
|
|
346
|
+
if (handle === void 0) return;
|
|
347
|
+
setBackground("wallpaper");
|
|
348
|
+
if (await saveVideoHandle(handle)) {
|
|
349
|
+
setWallpaper(`fsa:${handle.name}`);
|
|
350
|
+
} else {
|
|
351
|
+
const file = await handle.getFile();
|
|
352
|
+
void saveVideoBlob(file).then((id5) => {
|
|
353
|
+
if (id5 !== "") setWallpaper(id5);
|
|
354
|
+
else void fileToDataUrl(file).then(setWallpaper);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
} catch {
|
|
358
|
+
}
|
|
359
|
+
})();
|
|
360
|
+
} else {
|
|
361
|
+
videoRef.current?.click();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
const onChooseVideo = () => {
|
|
365
|
+
if (wallpaper.startsWith("fsa:")) {
|
|
366
|
+
void (async () => {
|
|
367
|
+
const handle = await loadVideoHandle();
|
|
368
|
+
if (handle !== null) {
|
|
369
|
+
try {
|
|
370
|
+
const permission = await handle.queryPermission({ mode: "read" });
|
|
371
|
+
if (permission === "granted") {
|
|
372
|
+
authorizeVideo();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (permission === "prompt") {
|
|
376
|
+
const next = await handle.requestPermission({ mode: "read" });
|
|
377
|
+
if (next === "granted") {
|
|
378
|
+
authorizeVideo();
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
} catch {
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
pickVideo();
|
|
386
|
+
})();
|
|
387
|
+
} else {
|
|
388
|
+
pickVideo();
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
const bgMin = dark ? 0 : 50;
|
|
392
|
+
const bgMax = dark ? 50 : 100;
|
|
393
|
+
const bgDisplay = Math.min(bgMax, Math.max(bgMin, bgBrightness));
|
|
394
|
+
if (!enabled) return null;
|
|
395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.group, children: [
|
|
396
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.subGroup, children: [
|
|
397
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.subTitle, children: t("aqua.mode") }),
|
|
398
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.controls, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.row, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
399
|
+
Segmented,
|
|
400
|
+
{
|
|
401
|
+
label: t("aqua.mode"),
|
|
402
|
+
value: mode,
|
|
403
|
+
options: [
|
|
404
|
+
{ id: "mica", label: t("aqua.modeMica") },
|
|
405
|
+
{ id: "compat", label: t("aqua.modeCompat") }
|
|
406
|
+
],
|
|
407
|
+
onSelect: setMode
|
|
408
|
+
}
|
|
409
|
+
) }) })
|
|
410
|
+
] }),
|
|
411
|
+
mode === "mica" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.subGroup, children: [
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.subTitle, children: t("aqua.materialGroup") }),
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.controls, children: [
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.blur"), value: blur, min: 0, max: 40, step: 0.5, unit: "px", onChange: setBlur }),
|
|
415
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.frost"), value: frost, min: 0, max: 100, step: 1, unit: "%", onChange: setFrost })
|
|
416
|
+
] })
|
|
417
|
+
] }),
|
|
418
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.subGroup, children: [
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.subTitle, children: t("aqua.background") }),
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.controls, children: [
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.row, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
422
|
+
Segmented,
|
|
423
|
+
{
|
|
424
|
+
label: t("aqua.background"),
|
|
425
|
+
value: background,
|
|
426
|
+
options: [
|
|
427
|
+
{ id: "fluid", label: t("aqua.backgroundFluid") },
|
|
428
|
+
{ id: "wallpaper", label: t("aqua.backgroundWallpaper") }
|
|
429
|
+
],
|
|
430
|
+
onSelect: setBackground
|
|
431
|
+
}
|
|
432
|
+
) }),
|
|
433
|
+
background === "fluid" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
434
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.fluidHue"), value: fluidHue, min: 0, max: 360, step: 1, unit: "\xB0", onChange: setFluidHue }),
|
|
435
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.fluidDepth"), value: fluidDepth, min: 0, max: 100, step: 1, unit: "%", onChange: setFluidDepth })
|
|
436
|
+
] }),
|
|
437
|
+
background === "wallpaper" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
438
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.row, children: [
|
|
439
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.rowLabel, children: t("aqua.wallpaper") }),
|
|
440
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.wallpaperPick, children: [
|
|
441
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
442
|
+
"input",
|
|
443
|
+
{
|
|
444
|
+
ref: fileRef,
|
|
445
|
+
type: "file",
|
|
446
|
+
accept: "image/*",
|
|
447
|
+
className: stdin_default2.fileInput,
|
|
448
|
+
onChange: (e) => {
|
|
449
|
+
const file = e.target.files?.[0];
|
|
450
|
+
if (file !== void 0) {
|
|
451
|
+
setBackground("wallpaper");
|
|
452
|
+
void fileToDataUrl(file).then(setWallpaper);
|
|
453
|
+
}
|
|
454
|
+
e.target.value = "";
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
),
|
|
458
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
459
|
+
"input",
|
|
460
|
+
{
|
|
461
|
+
ref: videoRef,
|
|
462
|
+
type: "file",
|
|
463
|
+
accept: "video/mp4,video/webm,video/ogg,video/quicktime",
|
|
464
|
+
className: stdin_default2.fileInput,
|
|
465
|
+
onChange: (e) => {
|
|
466
|
+
const file = e.target.files?.[0];
|
|
467
|
+
if (file !== void 0) {
|
|
468
|
+
setBackground("wallpaper");
|
|
469
|
+
void saveVideoBlob(file).then((id5) => {
|
|
470
|
+
if (id5 !== "") {
|
|
471
|
+
setWallpaper(id5);
|
|
472
|
+
} else {
|
|
473
|
+
void fileToDataUrl(file).then(setWallpaper);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
e.target.value = "";
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: stdin_default2.pickButton, onClick: () => {
|
|
482
|
+
fileRef.current?.click();
|
|
483
|
+
}, children: t("aqua.chooseImage") }),
|
|
484
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: stdin_default2.pickButton, onClick: onChooseVideo, children: t("aqua.chooseVideo") }),
|
|
485
|
+
wallpaper !== "" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: stdin_default2.deleteButton, onClick: () => {
|
|
486
|
+
setWallpaper("");
|
|
487
|
+
}, children: t("aqua.deleteWallpaper") })
|
|
488
|
+
] })
|
|
489
|
+
] }),
|
|
490
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.knobHint, children: t("aqua.wallpaperHint") }),
|
|
491
|
+
!isVideoWallpaper && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
492
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.wallpaperBlur"), value: wallpaperBlur, min: 0, max: 40, step: 0.5, unit: "px", onChange: setWallpaperBlur }),
|
|
493
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.wallpaperFrost"), value: wallpaperFrost, min: 0, max: 100, step: 1, unit: "%", onChange: setWallpaperFrost })
|
|
494
|
+
] }),
|
|
495
|
+
isVideoWallpaper && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
496
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.videoBlur"), value: videoBlur, min: 0, max: 40, step: 0.5, unit: "px", onChange: setVideoBlur }),
|
|
497
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.videoBrightness"), value: videoBrightness, min: 0, max: 100, step: 1, unit: "%", onChange: setVideoBrightness }),
|
|
498
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.knobHint, children: t("aqua.videoHint") })
|
|
499
|
+
] })
|
|
500
|
+
] }),
|
|
501
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Knob, { label: t("aqua.bgBrightness"), value: bgDisplay, min: bgMin, max: bgMax, step: 1, unit: "%", onChange: setBgBrightness }),
|
|
502
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.knobHint, children: t(dark ? "aqua.bgBrightnessHintDark" : "aqua.bgBrightnessHintLight") })
|
|
503
|
+
] })
|
|
504
|
+
] }),
|
|
505
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.subGroup, children: [
|
|
506
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.subTitle, children: t("aqua.decorAmbient") }),
|
|
507
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.controls, children: [
|
|
508
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.row, children: [
|
|
509
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.rowLabel, children: t("aqua.whale") }),
|
|
510
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
511
|
+
"button",
|
|
512
|
+
{
|
|
513
|
+
type: "button",
|
|
514
|
+
className: whale ? stdin_default2.toggleOn : stdin_default2.toggle,
|
|
515
|
+
"aria-pressed": whale,
|
|
516
|
+
onClick: () => {
|
|
517
|
+
setWhale(!whale);
|
|
518
|
+
},
|
|
519
|
+
children: [
|
|
520
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.check, children: whale && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconCheckOutlineRegular, { size: 16 }) }),
|
|
521
|
+
whale ? t("aqua.enable") : t("aqua.disable")
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] }),
|
|
526
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.row, children: [
|
|
527
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.rowLabel, children: t("aqua.critters") }),
|
|
528
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
529
|
+
"button",
|
|
530
|
+
{
|
|
531
|
+
type: "button",
|
|
532
|
+
className: critters ? stdin_default2.toggleOn : stdin_default2.toggle,
|
|
533
|
+
"aria-pressed": critters,
|
|
534
|
+
onClick: () => {
|
|
535
|
+
setCritters(!critters);
|
|
536
|
+
},
|
|
537
|
+
children: [
|
|
538
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.check, children: critters && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconCheckOutlineRegular, { size: 16 }) }),
|
|
539
|
+
critters ? t("aqua.enable") : t("aqua.disable")
|
|
540
|
+
]
|
|
541
|
+
}
|
|
542
|
+
)
|
|
543
|
+
] }),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.row, children: [
|
|
545
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.rowLabel, children: t("aqua.mesh") }),
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
547
|
+
"button",
|
|
548
|
+
{
|
|
549
|
+
type: "button",
|
|
550
|
+
className: mesh ? stdin_default2.toggleOn : stdin_default2.toggle,
|
|
551
|
+
"aria-pressed": mesh,
|
|
552
|
+
onClick: () => {
|
|
553
|
+
setMesh(!mesh);
|
|
554
|
+
},
|
|
555
|
+
children: [
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.check, children: mesh && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconCheckOutlineRegular, { size: 16 }) }),
|
|
557
|
+
mesh ? t("aqua.enable") : t("aqua.disable")
|
|
558
|
+
]
|
|
559
|
+
}
|
|
560
|
+
)
|
|
561
|
+
] })
|
|
562
|
+
] })
|
|
563
|
+
] }),
|
|
564
|
+
mode === "mica" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.subGroup, children: [
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: stdin_default2.subTitle, children: t("aqua.decorHover") }),
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.controls, children: [
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.row, children: [
|
|
568
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.rowLabel, children: t("aqua.spotlight") }),
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
570
|
+
"button",
|
|
571
|
+
{
|
|
572
|
+
type: "button",
|
|
573
|
+
className: spotlight ? stdin_default2.toggleOn : stdin_default2.toggle,
|
|
574
|
+
"aria-pressed": spotlight,
|
|
575
|
+
onClick: () => {
|
|
576
|
+
setSpotlight(!spotlight);
|
|
577
|
+
},
|
|
578
|
+
children: [
|
|
579
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.check, children: spotlight && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconCheckOutlineRegular, { size: 16 }) }),
|
|
580
|
+
spotlight ? t("aqua.enable") : t("aqua.disable")
|
|
581
|
+
]
|
|
582
|
+
}
|
|
583
|
+
)
|
|
584
|
+
] }),
|
|
585
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: stdin_default2.row, children: [
|
|
586
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.rowLabel, children: t("aqua.press") }),
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
588
|
+
"button",
|
|
589
|
+
{
|
|
590
|
+
type: "button",
|
|
591
|
+
className: press ? stdin_default2.toggleOn : stdin_default2.toggle,
|
|
592
|
+
"aria-pressed": press,
|
|
593
|
+
onClick: () => {
|
|
594
|
+
setPress(!press);
|
|
595
|
+
},
|
|
596
|
+
children: [
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: stdin_default2.check, children: press && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconCheckOutlineRegular, { size: 16 }) }),
|
|
598
|
+
press ? t("aqua.enable") : t("aqua.disable")
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
)
|
|
602
|
+
] })
|
|
603
|
+
] })
|
|
604
|
+
] })
|
|
605
|
+
] });
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// src/client/settings-store.ts
|
|
609
|
+
var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
610
|
+
function createAquaRowStore() {
|
|
611
|
+
return (0, import_dsh_client_store.defineStore)({
|
|
612
|
+
init: () => ({
|
|
613
|
+
enabled: true,
|
|
614
|
+
mode: "mica",
|
|
615
|
+
blur: 20,
|
|
616
|
+
frost: 7,
|
|
617
|
+
fluidHue: 320,
|
|
618
|
+
fluidDepth: 25,
|
|
619
|
+
bgBrightness: 50,
|
|
620
|
+
dark: false,
|
|
621
|
+
background: "fluid",
|
|
622
|
+
wallpaper: "",
|
|
623
|
+
whale: true,
|
|
624
|
+
critters: true,
|
|
625
|
+
mesh: true,
|
|
626
|
+
spotlight: true,
|
|
627
|
+
press: true,
|
|
628
|
+
wallpaperBlur: 0,
|
|
629
|
+
wallpaperFrost: 0,
|
|
630
|
+
videoBlur: 6,
|
|
631
|
+
videoBrightness: 45,
|
|
632
|
+
revision: -1
|
|
633
|
+
}),
|
|
634
|
+
actions: {
|
|
635
|
+
sync: (d, next, revision) => {
|
|
636
|
+
if (revision <= d.revision) return;
|
|
637
|
+
d.enabled = next.enabled;
|
|
638
|
+
d.mode = next.mode;
|
|
639
|
+
d.blur = next.blur;
|
|
640
|
+
d.frost = next.frost;
|
|
641
|
+
d.fluidHue = next.fluidHue;
|
|
642
|
+
d.fluidDepth = next.fluidDepth;
|
|
643
|
+
d.bgBrightness = next.bgBrightness;
|
|
644
|
+
d.dark = next.dark;
|
|
645
|
+
d.background = next.background;
|
|
646
|
+
d.wallpaper = next.wallpaper;
|
|
647
|
+
d.whale = next.whale;
|
|
648
|
+
d.critters = next.critters;
|
|
649
|
+
d.mesh = next.mesh;
|
|
650
|
+
d.spotlight = next.spotlight;
|
|
651
|
+
d.press = next.press;
|
|
652
|
+
d.wallpaperBlur = next.wallpaperBlur;
|
|
653
|
+
d.wallpaperFrost = next.wallpaperFrost;
|
|
654
|
+
d.videoBlur = next.videoBlur;
|
|
655
|
+
d.videoBrightness = next.videoBrightness;
|
|
656
|
+
d.revision = revision;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// src/client/locales.ts
|
|
663
|
+
var NS = "settings.aqua";
|
|
664
|
+
var zh = {
|
|
665
|
+
"aqua.title": "\u73BB\u7483\u4E3B\u9898",
|
|
666
|
+
"aqua.description": "\u5168\u5C40\u73BB\u7483\u8D28\u611F\uFF0C\u4E91\u6BCD/\u517C\u5BB9\u53CC\u6A21\u5F0F\uFF0C\u6A21\u7CCA\u5EA6\u3001\u78E8\u7802\u5EA6\u3001\u80CC\u666F\u4E0E\u989C\u8272\u90FD\u53EF\u81EA\u7531\u8C03\u8282",
|
|
667
|
+
"aqua.enable": "\u5F00\u542F",
|
|
668
|
+
"aqua.disable": "\u5173\u95ED",
|
|
669
|
+
"aqua.mode": "\u6A21\u5F0F",
|
|
670
|
+
"aqua.modeMica": "\u4E91\u6BCD\u6548\u679C",
|
|
671
|
+
"aqua.modeCompat": "\u517C\u5BB9\u6A21\u5F0F",
|
|
672
|
+
"aqua.materialGroup": "\u73BB\u7483\u6750\u8D28",
|
|
673
|
+
"aqua.decorAmbient": "\u73AF\u5883\u88C5\u9970",
|
|
674
|
+
"aqua.decorHover": "\u60AC\u505C\u6548\u679C",
|
|
675
|
+
"aqua.whale": "\u7C92\u5B50\u9CB8\u9C7C",
|
|
676
|
+
"aqua.critters": "\u5C0F\u9C7C",
|
|
677
|
+
"aqua.mesh": "\u7F51\u72B6\u4EA4\u4E92",
|
|
678
|
+
"aqua.spotlight": "\u9F20\u6807\u8F89\u5149",
|
|
679
|
+
"aqua.press": "\u60AC\u505C\u4E0B\u538B",
|
|
680
|
+
"aqua.blur": "\u73BB\u7483\u6A21\u7CCA\u5EA6",
|
|
681
|
+
"aqua.frost": "\u78E8\u7802\u5EA6",
|
|
682
|
+
"aqua.fluidHue": "\u8272\u8C03",
|
|
683
|
+
"aqua.fluidDepth": "\u989C\u8272\u6DF1\u6D45",
|
|
684
|
+
"aqua.bgBrightness": "\u80CC\u666F\u4EAE\u5EA6",
|
|
685
|
+
"aqua.bgBrightnessHintDark": "\u6DF1\u8272\u6A21\u5F0F\uFF1A0 \u538B\u6697\u81F3\u7EAF\u9ED1\uFF0C50 \u539F\u6837",
|
|
686
|
+
"aqua.bgBrightnessHintLight": "\u6D45\u8272\u6A21\u5F0F\uFF1A50 \u539F\u6837\uFF0C100 \u63D0\u4EAE\u81F3\u7EAF\u767D",
|
|
687
|
+
"aqua.background": "\u80CC\u666F",
|
|
688
|
+
"aqua.backgroundFluid": "\u6D41\u4F53",
|
|
689
|
+
"aqua.backgroundWallpaper": "\u58C1\u7EB8",
|
|
690
|
+
"aqua.wallpaper": "\u58C1\u7EB8",
|
|
691
|
+
"aqua.wallpaperHint": "\u6D45\u8272\u58C1\u7EB8\u7528\u6D45\u8272\u6A21\u5F0F\uFF0C\u6DF1\u8272\u58C1\u7EB8\u7528\u6DF1\u8272\u6A21\u5F0F\u26A0\uFE0F",
|
|
692
|
+
"aqua.chooseImage": "\u9009\u62E9\u56FE\u7247",
|
|
693
|
+
"aqua.chooseVideo": "\u9009\u62E9\u89C6\u9891",
|
|
694
|
+
"aqua.deleteWallpaper": "\u5220\u9664",
|
|
695
|
+
"aqua.wallpaperBlur": "\u58C1\u7EB8\u6A21\u7CCA\u5EA6",
|
|
696
|
+
"aqua.wallpaperFrost": "\u58C1\u7EB8\u78E8\u7802\u5EA6",
|
|
697
|
+
"aqua.videoBlur": "\u89C6\u9891\u6A21\u7CCA\u5EA6",
|
|
698
|
+
"aqua.videoBrightness": "\u89C6\u9891\u4EAE\u5EA6",
|
|
699
|
+
"aqua.videoHint": "\u26A0\uFE0F\u89C6\u9891\u4F1A\u81EA\u52A8\u538B\u6697\u4EE5\u4FDD\u8BC1\u6587\u5B57\u6E05\u6670\uFF0C\u53EF\u7528\u6A21\u7CCA\u5EA6\u548C\u4EAE\u5EA6\u8C03\u8282\uFF1B\u5237\u65B0\u540E\u672A\u81EA\u52A8\u64AD\u653E\u65F6\u70B9\u4E00\u4E0B\u201C\u9009\u62E9\u89C6\u9891\u201D\u5373\u53EF\u6062\u590D"
|
|
700
|
+
};
|
|
701
|
+
var en = {
|
|
702
|
+
"aqua.title": "Glass theme",
|
|
703
|
+
"aqua.description": "Global glassmorphism with mica/compatibility modes \u2014 blur, frost, backdrop, and color all adjustable",
|
|
704
|
+
"aqua.enable": "On",
|
|
705
|
+
"aqua.disable": "Off",
|
|
706
|
+
"aqua.mode": "Mode",
|
|
707
|
+
"aqua.modeMica": "Mica",
|
|
708
|
+
"aqua.modeCompat": "Compatibility",
|
|
709
|
+
"aqua.materialGroup": "Glass material",
|
|
710
|
+
"aqua.decorAmbient": "Ambient",
|
|
711
|
+
"aqua.decorHover": "Hover effects",
|
|
712
|
+
"aqua.whale": "Particle whale",
|
|
713
|
+
"aqua.critters": "Fish",
|
|
714
|
+
"aqua.mesh": "Interactive mesh",
|
|
715
|
+
"aqua.spotlight": "Cursor glow",
|
|
716
|
+
"aqua.press": "Hover tilt",
|
|
717
|
+
"aqua.blur": "Glass blur",
|
|
718
|
+
"aqua.frost": "Frost",
|
|
719
|
+
"aqua.fluidHue": "Hue",
|
|
720
|
+
"aqua.fluidDepth": "Color depth",
|
|
721
|
+
"aqua.bgBrightness": "Background brightness",
|
|
722
|
+
"aqua.bgBrightnessHintDark": "Dark mode: 0 fades to pure black, 50 is unchanged",
|
|
723
|
+
"aqua.bgBrightnessHintLight": "Light mode: 50 is unchanged, 100 brightens to pure white",
|
|
724
|
+
"aqua.background": "Backdrop",
|
|
725
|
+
"aqua.backgroundFluid": "Fluid",
|
|
726
|
+
"aqua.backgroundWallpaper": "Wallpaper",
|
|
727
|
+
"aqua.wallpaper": "Wallpaper",
|
|
728
|
+
"aqua.wallpaperHint": "Use light mode for light wallpapers, dark mode for dark wallpapers \u26A0\uFE0F",
|
|
729
|
+
"aqua.chooseImage": "Choose image",
|
|
730
|
+
"aqua.chooseVideo": "Choose video",
|
|
731
|
+
"aqua.deleteWallpaper": "Delete",
|
|
732
|
+
"aqua.wallpaperBlur": "Wallpaper blur",
|
|
733
|
+
"aqua.wallpaperFrost": "Wallpaper frost",
|
|
734
|
+
"aqua.videoBlur": "Video blur",
|
|
735
|
+
"aqua.videoBrightness": "Video brightness",
|
|
736
|
+
"aqua.videoHint": '\u26A0\uFE0F The video is dimmed automatically to keep text readable \u2014 adjust blur and brightness here; if it does not play after a reload, click "Choose video" once to restore access'
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
// src/client/critters.ts
|
|
740
|
+
var FISH_PATH = "M22.9168 1.43018C22.6713 1.31018 22.5658 1.53918 22.4223 1.65519C22.3733 1.69269 22.3318 1.74169 22.2903 1.78669C21.9317 2.1697 21.5127 2.42121 20.9657 2.39121C20.1657 2.34621 19.4827 2.59771 18.8787 3.20973C18.7502 2.45521 18.3236 2.0047 17.6746 1.71569C17.3351 1.56568 16.9916 1.41518 16.7536 1.08867C16.5876 0.856163 16.5421 0.597155 16.4591 0.341647C16.4061 0.187643 16.3536 0.0301382 16.1761 0.00363739C15.9836 -0.0263635 15.9081 0.135141 15.8326 0.270145C15.5306 0.822162 15.4136 1.43018 15.4251 2.0462C15.4516 3.43174 16.0366 4.53527 17.1991 5.3203C17.3311 5.4103 17.3651 5.5003 17.3236 5.63181C17.2441 5.90231 17.1501 6.16482 17.0671 6.43533C17.0141 6.60784 16.9351 6.64584 16.7501 6.57033C16.1121 6.30383 15.5611 5.90931 15.074 5.4328C14.2475 4.63328 13.5 3.75075 12.568 3.05973C12.349 2.89822 12.13 2.74822 11.9034 2.60522C10.9524 1.68169 12.028 0.923165 12.277 0.833162C12.5375 0.739159 12.3675 0.41615 11.5259 0.42015C10.6844 0.42365 9.91439 0.705658 8.93286 1.08117C8.78935 1.13767 8.63835 1.17867 8.48384 1.21267C7.59332 1.04367 6.66829 1.00617 5.70226 1.11517C3.88321 1.31768 2.43016 2.1777 1.36213 3.64575C0.0790928 5.4103 -0.222916 7.41536 0.146595 9.50642C0.535106 11.7105 1.66014 13.535 3.38869 14.9616C5.18125 16.4406 7.24581 17.1657 9.60138 17.0266C11.0319 16.9441 12.6245 16.7526 14.421 15.2321C14.874 15.4576 15.3496 15.5476 16.1381 15.6151C16.7456 15.6716 17.3306 15.5851 17.7836 15.4911C18.4931 15.3411 18.4441 14.6841 18.1876 14.5636C16.1081 13.595 16.5646 13.9891 16.1496 13.67C17.2061 12.42 18.8202 10.1979 19.3182 7.17235C19.3672 6.83834 19.4297 6.36783 19.4222 6.09732C19.4182 5.93231 19.4562 5.86831 19.6447 5.84931C20.1657 5.78931 20.6712 5.64681 21.1357 5.3913C22.4833 4.65528 23.0268 3.44624 23.1548 1.9972C23.1738 1.77569 23.1508 1.54668 22.9168 1.43018ZM11.1749 14.4736C9.15936 12.889 8.18184 12.3675 7.77832 12.39C7.40081 12.4125 7.46881 12.8445 7.55182 13.126C7.63882 13.404 7.75182 13.5955 7.91033 13.8396C8.01983 14.0011 8.09533 14.2411 7.80083 14.4216C7.15181 14.8231 6.02327 14.2866 5.97027 14.2601C4.65673 13.4865 3.5587 12.4655 2.78467 11.069C2.03715 9.72493 1.60314 8.28289 1.53164 6.74384C1.51264 6.37233 1.62214 6.24082 1.99215 6.17332C2.47916 6.08332 2.98118 6.06432 3.46769 6.13582C5.52476 6.43633 7.27581 7.35586 8.74385 8.8129C9.58188 9.64243 10.2159 10.634 10.8689 11.6025C11.5634 12.631 12.3105 13.611 13.262 14.4146C13.598 14.6961 13.866 14.9101 14.1225 15.0681C13.349 15.1546 12.058 15.1731 11.1749 14.4746L11.1749 14.4736ZM12.141 8.25988C12.141 8.09488 12.273 7.96338 12.439 7.96338C12.4765 7.96338 12.5105 7.97088 12.541 7.98188C12.5825 7.99688 12.6205 8.01938 12.6505 8.05338C12.7035 8.10588 12.7335 8.18088 12.7335 8.25988C12.7335 8.42489 12.6015 8.55639 12.4355 8.55639C12.2695 8.55639 12.141 8.42489 12.141 8.25988ZM15.1415 9.79893C14.949 9.87793 14.7565 9.94544 14.5715 9.95294C14.2845 9.96794 13.9715 9.85143 13.8015 9.70893C13.5375 9.48742 13.3485 9.36342 13.2695 8.97691C13.2355 8.8119 13.2545 8.55639 13.2845 8.40989C13.3525 8.09438 13.277 7.89187 13.0545 7.70787C12.8735 7.55786 12.643 7.51636 12.39 7.51636C12.2955 7.51636 12.209 7.47486 12.1445 7.44136C12.039 7.38886 11.9519 7.25735 12.035 7.09585C12.0615 7.04335 12.19 6.91584 12.22 6.89334C12.5635 6.69784 12.9595 6.76184 13.326 6.90834C13.6655 7.04735 13.9225 7.30236 14.292 7.66287C14.6695 8.09838 14.7375 8.21838 14.9525 8.54539C15.1225 8.8009 15.277 9.06341 15.3831 9.36392C15.4471 9.55142 15.3641 9.70493 15.1415 9.79893Z";
|
|
741
|
+
function svg(critter, viewBox, width, style, body) {
|
|
742
|
+
return `<svg data-aqua-critter="${critter}" viewBox="${viewBox}" width="${width}" style="${style}" aria-hidden="true">${body}</svg>`;
|
|
743
|
+
}
|
|
744
|
+
function fish(style, width) {
|
|
745
|
+
return svg("fish", "0 0 23.16 17.04", width, style, `<path d="${FISH_PATH}" fill="currentColor"/>`);
|
|
746
|
+
}
|
|
747
|
+
function fishLeft(style, width) {
|
|
748
|
+
return svg("fish-left", "0 0 23.16 17.04", width, style, `<path d="${FISH_PATH}" fill="currentColor"/>`);
|
|
749
|
+
}
|
|
750
|
+
function bubble(style, size) {
|
|
751
|
+
return svg(
|
|
752
|
+
"bubble",
|
|
753
|
+
"0 0 8 8",
|
|
754
|
+
size,
|
|
755
|
+
style,
|
|
756
|
+
'<circle cx="4" cy="4" r="3" fill="none" stroke="currentColor" stroke-width="1"/>'
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
function plankton(style) {
|
|
760
|
+
return svg("plankton", "0 0 3 3", 3, style, '<circle cx="1.5" cy="1.5" r="1.5" fill="currentColor"/>');
|
|
761
|
+
}
|
|
762
|
+
var AMBIENT_SCENE = [
|
|
763
|
+
"<canvas data-dsh-aqua-fluid-canvas></canvas>",
|
|
764
|
+
fish("top:22%;left:58%;animation-duration:9s", 30),
|
|
765
|
+
fishLeft("top:36%;left:10%;animation-duration:14s;animation-delay:-4s", 20),
|
|
766
|
+
fish("top:64%;left:76%;animation-duration:19s;animation-delay:-9s;opacity:0.55", 14),
|
|
767
|
+
bubble("bottom:8%;left:9%;animation-duration:8s", 7),
|
|
768
|
+
bubble("bottom:5%;left:13%;animation-duration:10s;animation-delay:2.5s", 5),
|
|
769
|
+
bubble("bottom:10%;left:17%;animation-duration:9s;animation-delay:5s", 6),
|
|
770
|
+
bubble("bottom:9%;left:82%;animation-duration:11s;animation-delay:1.5s", 8),
|
|
771
|
+
bubble("bottom:6%;left:87%;animation-duration:8s;animation-delay:4s", 5),
|
|
772
|
+
plankton("top:14%;left:42%;animation-delay:-1s"),
|
|
773
|
+
plankton("top:32%;left:70%;animation-delay:-3s"),
|
|
774
|
+
plankton("top:72%;left:18%;animation-delay:-2s"),
|
|
775
|
+
plankton("top:56%;left:86%;animation-delay:-4s")
|
|
776
|
+
].join("");
|
|
777
|
+
function ensureAmbientScene() {
|
|
778
|
+
const existing = document.querySelector("[data-dsh-aqua-ambient]");
|
|
779
|
+
if (existing !== null) return existing;
|
|
780
|
+
const holder = document.createElement("div");
|
|
781
|
+
holder.innerHTML = `<div data-dsh-aqua-ambient aria-hidden="true">${AMBIENT_SCENE}</div>`;
|
|
782
|
+
const node = holder.firstElementChild;
|
|
783
|
+
if (!(node instanceof HTMLElement)) throw new Error("ui-aqua: ambient scene markup failed to parse");
|
|
784
|
+
document.body.prepend(node);
|
|
785
|
+
if (document.querySelector("[data-dsh-aqua-wallpaper-layer]") === null) {
|
|
786
|
+
const wallpaper = document.createElement("div");
|
|
787
|
+
wallpaper.setAttribute("data-dsh-aqua-wallpaper", "");
|
|
788
|
+
wallpaper.setAttribute("data-dsh-aqua-wallpaper-layer", "");
|
|
789
|
+
wallpaper.setAttribute("aria-hidden", "true");
|
|
790
|
+
wallpaper.innerHTML = '<img data-dsh-aqua-wallpaper-img alt=""><video data-dsh-aqua-wallpaper-video loop playsinline preload="auto"></video>';
|
|
791
|
+
document.body.prepend(wallpaper);
|
|
792
|
+
}
|
|
793
|
+
return node;
|
|
794
|
+
}
|
|
795
|
+
function removeAmbientScene() {
|
|
796
|
+
for (const node of document.querySelectorAll("[data-dsh-aqua-ambient]")) node.remove();
|
|
797
|
+
for (const node of document.querySelectorAll("[data-dsh-aqua-wallpaper-layer]")) node.remove();
|
|
798
|
+
}
|
|
799
|
+
function ensurePageFades() {
|
|
800
|
+
if (document.querySelector("[data-dsh-aqua-fade]") !== null) return;
|
|
801
|
+
const top = document.createElement("div");
|
|
802
|
+
top.setAttribute("data-dsh-aqua-fade", "top");
|
|
803
|
+
top.setAttribute("aria-hidden", "true");
|
|
804
|
+
const bottom = document.createElement("div");
|
|
805
|
+
bottom.setAttribute("data-dsh-aqua-fade", "bottom");
|
|
806
|
+
bottom.setAttribute("aria-hidden", "true");
|
|
807
|
+
document.body.appendChild(top);
|
|
808
|
+
document.body.appendChild(bottom);
|
|
809
|
+
}
|
|
810
|
+
function removePageFades() {
|
|
811
|
+
for (const el of document.querySelectorAll("[data-dsh-aqua-fade]")) el.remove();
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// src/client/fluid-shader.ts
|
|
815
|
+
var SITE_FLUID_PARAMS = {
|
|
816
|
+
mouseRadius: 0.22,
|
|
817
|
+
mouseStrength: 1.1,
|
|
818
|
+
decay: 0.96,
|
|
819
|
+
distortBoost: 1.35,
|
|
820
|
+
noiseBoost: 0,
|
|
821
|
+
swirlBoost: 0.45,
|
|
822
|
+
speed: 14,
|
|
823
|
+
distortion: 20,
|
|
824
|
+
swirl: 12,
|
|
825
|
+
swirlIterations: 8,
|
|
826
|
+
scale: 0.5,
|
|
827
|
+
rotation: -5,
|
|
828
|
+
proportion: 50,
|
|
829
|
+
softness: 100,
|
|
830
|
+
shapeScale: 10,
|
|
831
|
+
offsetX: 0,
|
|
832
|
+
offsetY: 65,
|
|
833
|
+
color1: "#8AA3D6",
|
|
834
|
+
color2: "#FFFFFF",
|
|
835
|
+
color3: "#FFFFFF"
|
|
836
|
+
};
|
|
837
|
+
var VERTEX_SHADER = `#version 300 es
|
|
838
|
+
in vec4 a_position;
|
|
839
|
+
out vec2 vUv;
|
|
840
|
+
void main() {
|
|
841
|
+
vUv = a_position.xy * 0.5 + 0.5;
|
|
842
|
+
gl_Position = a_position;
|
|
843
|
+
}
|
|
844
|
+
`;
|
|
845
|
+
var FLOW_SHADER = `#version 300 es
|
|
846
|
+
precision mediump float;
|
|
847
|
+
in vec2 vUv;
|
|
848
|
+
uniform sampler2D u_prev;
|
|
849
|
+
uniform vec2 u_mouse;
|
|
850
|
+
uniform vec2 u_velocity;
|
|
851
|
+
uniform float u_brushRadius;
|
|
852
|
+
uniform float u_brushStrength;
|
|
853
|
+
uniform float u_decay;
|
|
854
|
+
out vec4 fragColor;
|
|
855
|
+
|
|
856
|
+
void main() {
|
|
857
|
+
vec4 prev = texture(u_prev, vUv);
|
|
858
|
+
|
|
859
|
+
prev.r *= u_decay;
|
|
860
|
+
prev.gb = mix(vec2(0.5), prev.gb, u_decay);
|
|
861
|
+
|
|
862
|
+
float dist = distance(vUv, u_mouse);
|
|
863
|
+
|
|
864
|
+
float influence = exp(-dist * dist / (u_brushRadius * u_brushRadius * 0.5));
|
|
865
|
+
influence = max(0.0, influence - 0.01);
|
|
866
|
+
|
|
867
|
+
float speed = length(u_velocity);
|
|
868
|
+
float presenceStrength = u_brushStrength * 0.3;
|
|
869
|
+
float velBonus = min(speed * 3.0, 0.7) * u_brushStrength;
|
|
870
|
+
float totalStrength = presenceStrength + velBonus;
|
|
871
|
+
|
|
872
|
+
prev.r = max(prev.r, influence * totalStrength);
|
|
873
|
+
float blendAmt = influence * min(totalStrength, 0.4) * 0.3;
|
|
874
|
+
prev.g = mix(prev.g, clamp(u_velocity.x * 2.0 + 0.5, 0.0, 1.0), blendAmt);
|
|
875
|
+
prev.b = mix(prev.b, clamp(u_velocity.y * 2.0 + 0.5, 0.0, 1.0), blendAmt);
|
|
876
|
+
|
|
877
|
+
fragColor = prev;
|
|
878
|
+
}
|
|
879
|
+
`;
|
|
880
|
+
var DISPLAY_SHADER = `#version 300 es
|
|
881
|
+
precision mediump float;
|
|
882
|
+
in vec2 vUv;
|
|
883
|
+
uniform float u_time;
|
|
884
|
+
uniform float u_pixelRatio;
|
|
885
|
+
uniform vec2 u_resolution;
|
|
886
|
+
uniform float u_scale;
|
|
887
|
+
uniform float u_rotation;
|
|
888
|
+
uniform vec4 u_color1, u_color2, u_color3;
|
|
889
|
+
uniform float u_colorCount;
|
|
890
|
+
uniform float u_proportion;
|
|
891
|
+
uniform float u_softness;
|
|
892
|
+
uniform float u_shape;
|
|
893
|
+
uniform float u_shapeScale;
|
|
894
|
+
uniform float u_distortion;
|
|
895
|
+
uniform float u_swirl;
|
|
896
|
+
uniform float u_swirlIterations;
|
|
897
|
+
uniform vec2 u_offset;
|
|
898
|
+
uniform sampler2D u_flowmap;
|
|
899
|
+
uniform float u_distortBoost;
|
|
900
|
+
uniform float u_noiseBoost;
|
|
901
|
+
uniform float u_swirlBoost;
|
|
902
|
+
out vec4 fragColor;
|
|
903
|
+
|
|
904
|
+
#define TWO_PI 6.28318530718
|
|
905
|
+
#define PI 3.14159265358979323846
|
|
906
|
+
|
|
907
|
+
vec2 rotate(vec2 uv, float th) { return mat2(cos(th), sin(th), -sin(th), cos(th)) * uv; }
|
|
908
|
+
float random(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); }
|
|
909
|
+
float noise(vec2 st) {
|
|
910
|
+
vec2 i = floor(st); vec2 f = fract(st);
|
|
911
|
+
float a = random(i), b = random(i + vec2(1,0)), c = random(i + vec2(0,1)), d = random(i + vec2(1,1));
|
|
912
|
+
vec2 u = f*f*(3.0-2.0*f);
|
|
913
|
+
return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
vec3 blend_multi(float mixer, float softness) {
|
|
917
|
+
float edge = 1.0 - softness;
|
|
918
|
+
vec3 col = u_color1.rgb;
|
|
919
|
+
if (u_colorCount > 1.5) { col = mix(col, u_color2.rgb, smoothstep(0.0 + 0.35*edge, 0.7 - 0.35*edge, mixer)); }
|
|
920
|
+
if (u_colorCount > 2.5) { col = mix(col, u_color3.rgb, smoothstep(0.3 + 0.35*edge, 1.0 - 0.35*edge, mixer)); }
|
|
921
|
+
return col;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
void main() {
|
|
925
|
+
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
|
|
926
|
+
float t = .5 * u_time;
|
|
927
|
+
float ns = .0005 + .006 * u_scale;
|
|
928
|
+
uv -= .5; uv *= (ns * u_resolution); uv = rotate(uv, u_rotation * .5 * PI);
|
|
929
|
+
uv /= u_pixelRatio; uv += .5; uv += u_offset;
|
|
930
|
+
|
|
931
|
+
vec2 fragUV = gl_FragCoord.xy / u_resolution.xy;
|
|
932
|
+
vec4 flow = texture(u_flowmap, fragUV);
|
|
933
|
+
float influence = flow.r;
|
|
934
|
+
vec2 flowDir = (flow.gb - 0.5) * 2.0;
|
|
935
|
+
|
|
936
|
+
float n1 = noise(uv + t), n2 = noise(uv*2. - t);
|
|
937
|
+
float angle = n1 * TWO_PI;
|
|
938
|
+
|
|
939
|
+
float totalDistortion = u_distortion + influence * u_distortBoost;
|
|
940
|
+
uv.x += 4. * totalDistortion * n2 * cos(angle);
|
|
941
|
+
uv.y += 4. * totalDistortion * n2 * sin(angle);
|
|
942
|
+
|
|
943
|
+
uv += flowDir * influence * 0.15;
|
|
944
|
+
|
|
945
|
+
if (influence > 0.001) {
|
|
946
|
+
float localNoise = noise(uv * 2.0 + t * 1.5);
|
|
947
|
+
uv += influence * u_noiseBoost * vec2(cos(localNoise * TWO_PI), sin(localNoise * TWO_PI));
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
float iters = ceil(clamp(u_swirlIterations, 1., 30.));
|
|
951
|
+
float swirlAmt = clamp(u_swirl, 0., 2.) + influence * u_swirlBoost;
|
|
952
|
+
for (float i = 1.; i <= 30.0; i++) {
|
|
953
|
+
if (i > iters) break;
|
|
954
|
+
uv.x += swirlAmt / i * cos(t + i*1.5*uv.y);
|
|
955
|
+
uv.y += swirlAmt / i * cos(t + i*1.*uv.x);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
float proportion = clamp(u_proportion, 0., 1.);
|
|
959
|
+
vec2 cuv = uv * (.5 + 3.5 * u_shapeScale);
|
|
960
|
+
float shape = .5 + .5 * sin(cuv.x) * cos(cuv.y);
|
|
961
|
+
float mixer = shape + .48 * sign(proportion - .5) * pow(abs(proportion - .5), .5);
|
|
962
|
+
vec3 col = blend_multi(mixer, clamp(u_softness, 0., 1.));
|
|
963
|
+
fragColor = vec4(col, 1.0);
|
|
964
|
+
}
|
|
965
|
+
`;
|
|
966
|
+
function hexToRgb(value) {
|
|
967
|
+
const hex = value.replace("#", "");
|
|
968
|
+
return [
|
|
969
|
+
parseInt(hex.slice(0, 2), 16) / 255,
|
|
970
|
+
parseInt(hex.slice(2, 4), 16) / 255,
|
|
971
|
+
parseInt(hex.slice(4, 6), 16) / 255
|
|
972
|
+
];
|
|
973
|
+
}
|
|
974
|
+
function attachFluidShader(canvas, params) {
|
|
975
|
+
const gl = canvas.getContext("webgl2", {
|
|
976
|
+
alpha: true,
|
|
977
|
+
premultipliedAlpha: false,
|
|
978
|
+
powerPreference: "low-power"
|
|
979
|
+
});
|
|
980
|
+
if (gl === null) {
|
|
981
|
+
return {
|
|
982
|
+
setParams: () => {
|
|
983
|
+
},
|
|
984
|
+
stir: () => {
|
|
985
|
+
},
|
|
986
|
+
dispose: () => {
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
const compile = (type, source) => {
|
|
991
|
+
const shader = gl.createShader(type);
|
|
992
|
+
if (shader === null) return null;
|
|
993
|
+
gl.shaderSource(shader, source);
|
|
994
|
+
gl.compileShader(shader);
|
|
995
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
996
|
+
console.error("ui-aqua fluid shader:", gl.getShaderInfoLog(shader));
|
|
997
|
+
return null;
|
|
998
|
+
}
|
|
999
|
+
return shader;
|
|
1000
|
+
};
|
|
1001
|
+
const link = (fragment) => {
|
|
1002
|
+
const vertex = compile(gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
1003
|
+
const frag = compile(gl.FRAGMENT_SHADER, fragment);
|
|
1004
|
+
if (vertex === null || frag === null) return null;
|
|
1005
|
+
const program = gl.createProgram();
|
|
1006
|
+
if (program === null) return null;
|
|
1007
|
+
gl.attachShader(program, vertex);
|
|
1008
|
+
gl.attachShader(program, frag);
|
|
1009
|
+
gl.linkProgram(program);
|
|
1010
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
1011
|
+
console.error("ui-aqua fluid link:", gl.getProgramInfoLog(program));
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
1014
|
+
return program;
|
|
1015
|
+
};
|
|
1016
|
+
const flowProgram = link(FLOW_SHADER);
|
|
1017
|
+
const displayProgram = link(DISPLAY_SHADER);
|
|
1018
|
+
if (flowProgram === null || displayProgram === null) {
|
|
1019
|
+
return {
|
|
1020
|
+
setParams: () => {
|
|
1021
|
+
},
|
|
1022
|
+
stir: () => {
|
|
1023
|
+
},
|
|
1024
|
+
dispose: () => {
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
const flow = {
|
|
1029
|
+
prev: gl.getUniformLocation(flowProgram, "u_prev"),
|
|
1030
|
+
mouse: gl.getUniformLocation(flowProgram, "u_mouse"),
|
|
1031
|
+
velocity: gl.getUniformLocation(flowProgram, "u_velocity"),
|
|
1032
|
+
brushRadius: gl.getUniformLocation(flowProgram, "u_brushRadius"),
|
|
1033
|
+
brushStrength: gl.getUniformLocation(flowProgram, "u_brushStrength"),
|
|
1034
|
+
decay: gl.getUniformLocation(flowProgram, "u_decay")
|
|
1035
|
+
};
|
|
1036
|
+
const display = {
|
|
1037
|
+
time: gl.getUniformLocation(displayProgram, "u_time"),
|
|
1038
|
+
pixelRatio: gl.getUniformLocation(displayProgram, "u_pixelRatio"),
|
|
1039
|
+
resolution: gl.getUniformLocation(displayProgram, "u_resolution"),
|
|
1040
|
+
scale: gl.getUniformLocation(displayProgram, "u_scale"),
|
|
1041
|
+
rotation: gl.getUniformLocation(displayProgram, "u_rotation"),
|
|
1042
|
+
offset: gl.getUniformLocation(displayProgram, "u_offset"),
|
|
1043
|
+
color1: gl.getUniformLocation(displayProgram, "u_color1"),
|
|
1044
|
+
color2: gl.getUniformLocation(displayProgram, "u_color2"),
|
|
1045
|
+
color3: gl.getUniformLocation(displayProgram, "u_color3"),
|
|
1046
|
+
colorCount: gl.getUniformLocation(displayProgram, "u_colorCount"),
|
|
1047
|
+
proportion: gl.getUniformLocation(displayProgram, "u_proportion"),
|
|
1048
|
+
softness: gl.getUniformLocation(displayProgram, "u_softness"),
|
|
1049
|
+
shape: gl.getUniformLocation(displayProgram, "u_shape"),
|
|
1050
|
+
shapeScale: gl.getUniformLocation(displayProgram, "u_shapeScale"),
|
|
1051
|
+
distortion: gl.getUniformLocation(displayProgram, "u_distortion"),
|
|
1052
|
+
swirl: gl.getUniformLocation(displayProgram, "u_swirl"),
|
|
1053
|
+
swirlIterations: gl.getUniformLocation(displayProgram, "u_swirlIterations"),
|
|
1054
|
+
flowmap: gl.getUniformLocation(displayProgram, "u_flowmap"),
|
|
1055
|
+
distortBoost: gl.getUniformLocation(displayProgram, "u_distortBoost"),
|
|
1056
|
+
noiseBoost: gl.getUniformLocation(displayProgram, "u_noiseBoost"),
|
|
1057
|
+
swirlBoost: gl.getUniformLocation(displayProgram, "u_swirlBoost")
|
|
1058
|
+
};
|
|
1059
|
+
const quadBuffer = gl.createBuffer();
|
|
1060
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
|
|
1061
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
1062
|
+
const bindQuad = (program) => {
|
|
1063
|
+
const position = gl.getAttribLocation(program, "a_position");
|
|
1064
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
|
|
1065
|
+
gl.enableVertexAttribArray(position);
|
|
1066
|
+
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
|
|
1067
|
+
};
|
|
1068
|
+
const makeTarget = (width2, height2, initial2) => {
|
|
1069
|
+
const tex = gl.createTexture();
|
|
1070
|
+
if (tex === null) throw new Error("ui-aqua fluid: texture allocation failed");
|
|
1071
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
1072
|
+
if (initial2 !== void 0) {
|
|
1073
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width2, height2, 0, gl.RGBA, gl.UNSIGNED_BYTE, initial2);
|
|
1074
|
+
} else {
|
|
1075
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width2, height2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
1076
|
+
}
|
|
1077
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
1078
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
1079
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
1080
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
1081
|
+
const fbo = gl.createFramebuffer();
|
|
1082
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
|
1083
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
|
1084
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
1085
|
+
return { fbo, tex };
|
|
1086
|
+
};
|
|
1087
|
+
let width = 0;
|
|
1088
|
+
let height = 0;
|
|
1089
|
+
let flowWidth = 0;
|
|
1090
|
+
let flowHeight = 0;
|
|
1091
|
+
let flip = false;
|
|
1092
|
+
let current = { ...params };
|
|
1093
|
+
const pointer = { x: 0.5, y: 0.5, smoothX: 0.5, smoothY: 0.5, vx: 0, vy: 0, svx: 0, svy: 0 };
|
|
1094
|
+
const dprCap = Math.min(window.devicePixelRatio || 1, 1.5);
|
|
1095
|
+
width = Math.round(canvas.clientWidth * dprCap);
|
|
1096
|
+
height = Math.round(canvas.clientHeight * dprCap);
|
|
1097
|
+
canvas.width = width;
|
|
1098
|
+
canvas.height = height;
|
|
1099
|
+
flowWidth = Math.round(width / 4);
|
|
1100
|
+
flowHeight = Math.round(height / 4);
|
|
1101
|
+
const initial = new Uint8Array(flowWidth * flowHeight * 4);
|
|
1102
|
+
for (let i = 0; i < flowWidth * flowHeight; i += 1) {
|
|
1103
|
+
initial[4 * i] = 0;
|
|
1104
|
+
initial[4 * i + 1] = 128;
|
|
1105
|
+
initial[4 * i + 2] = 128;
|
|
1106
|
+
initial[4 * i + 3] = 255;
|
|
1107
|
+
}
|
|
1108
|
+
let targetA = makeTarget(flowWidth, flowHeight, initial);
|
|
1109
|
+
let targetB = makeTarget(flowWidth, flowHeight, initial);
|
|
1110
|
+
const coarse = window.matchMedia("(hover: none), (pointer: coarse)").matches;
|
|
1111
|
+
const ua = navigator;
|
|
1112
|
+
const windows = ua.userAgentData ? ua.userAgentData.platform === "Windows" : navigator.userAgent.includes("Windows");
|
|
1113
|
+
const onMouseMove = (event) => {
|
|
1114
|
+
const rect = canvas.getBoundingClientRect();
|
|
1115
|
+
pointer.x = (event.clientX - rect.left) / rect.width;
|
|
1116
|
+
pointer.y = 1 - (event.clientY - rect.top) / rect.height;
|
|
1117
|
+
};
|
|
1118
|
+
if (!coarse && !windows) window.addEventListener("mousemove", onMouseMove);
|
|
1119
|
+
const start = performance.now();
|
|
1120
|
+
let raf = 0;
|
|
1121
|
+
let previous = 0;
|
|
1122
|
+
const step = 1e3 / 30;
|
|
1123
|
+
const frame = (now) => {
|
|
1124
|
+
raf = requestAnimationFrame(frame);
|
|
1125
|
+
if (now - previous < step) return;
|
|
1126
|
+
previous = now - (now - previous) % step;
|
|
1127
|
+
const ratio = Math.min(window.devicePixelRatio || 1, 1.5);
|
|
1128
|
+
const nextWidth = Math.round(canvas.clientWidth * ratio);
|
|
1129
|
+
const nextHeight = Math.round(canvas.clientHeight * ratio);
|
|
1130
|
+
if (nextWidth !== width || nextHeight !== height) {
|
|
1131
|
+
width = nextWidth;
|
|
1132
|
+
height = nextHeight;
|
|
1133
|
+
canvas.width = width;
|
|
1134
|
+
canvas.height = height;
|
|
1135
|
+
}
|
|
1136
|
+
const p = current;
|
|
1137
|
+
const s = pointer;
|
|
1138
|
+
s.svx *= 0.94;
|
|
1139
|
+
s.svy *= 0.94;
|
|
1140
|
+
s.smoothX += (s.x - s.smoothX) * 0.12;
|
|
1141
|
+
s.smoothY += (s.y - s.smoothY) * 0.12;
|
|
1142
|
+
s.svx += ((s.x - s.smoothX) * 0.5 - s.svx) * 0.15;
|
|
1143
|
+
s.svy += ((s.y - s.smoothY) * 0.5 - s.svy) * 0.15;
|
|
1144
|
+
const read = flip ? targetA : targetB;
|
|
1145
|
+
const write = flip ? targetB : targetA;
|
|
1146
|
+
flip = !flip;
|
|
1147
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, write.fbo);
|
|
1148
|
+
gl.viewport(0, 0, flowWidth, flowHeight);
|
|
1149
|
+
gl.useProgram(flowProgram);
|
|
1150
|
+
bindQuad(flowProgram);
|
|
1151
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
1152
|
+
gl.bindTexture(gl.TEXTURE_2D, read.tex);
|
|
1153
|
+
gl.uniform1i(flow.prev, 0);
|
|
1154
|
+
gl.uniform2f(flow.mouse, s.smoothX, s.smoothY);
|
|
1155
|
+
gl.uniform2f(flow.velocity, s.svx, s.svy);
|
|
1156
|
+
gl.uniform1f(flow.brushRadius, p.mouseRadius);
|
|
1157
|
+
gl.uniform1f(flow.brushStrength, p.mouseStrength);
|
|
1158
|
+
gl.uniform1f(flow.decay, p.decay);
|
|
1159
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
1160
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
1161
|
+
gl.viewport(0, 0, width, height);
|
|
1162
|
+
gl.useProgram(displayProgram);
|
|
1163
|
+
bindQuad(displayProgram);
|
|
1164
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
1165
|
+
gl.bindTexture(gl.TEXTURE_2D, write.tex);
|
|
1166
|
+
gl.uniform1i(display.flowmap, 0);
|
|
1167
|
+
const time = (performance.now() - start) * 1e-3 * (p.speed / 100);
|
|
1168
|
+
gl.uniform1f(display.time, time);
|
|
1169
|
+
gl.uniform1f(display.pixelRatio, window.devicePixelRatio || 1);
|
|
1170
|
+
gl.uniform2f(display.resolution, width, height);
|
|
1171
|
+
gl.uniform1f(display.scale, p.scale);
|
|
1172
|
+
gl.uniform1f(display.rotation, p.rotation / 90);
|
|
1173
|
+
gl.uniform2f(display.offset, p.offsetX / 100, p.offsetY / 100);
|
|
1174
|
+
const c1 = hexToRgb(p.color1 || "#2E58A4");
|
|
1175
|
+
const c2 = hexToRgb(p.color2 || "#D2E2EE");
|
|
1176
|
+
const c3 = hexToRgb(p.color3 || "#FFFFFF");
|
|
1177
|
+
gl.uniform4f(display.color1, c1[0], c1[1], c1[2], 1);
|
|
1178
|
+
gl.uniform4f(display.color2, c2[0], c2[1], c2[2], 1);
|
|
1179
|
+
gl.uniform4f(display.color3, c3[0], c3[1], c3[2], 1);
|
|
1180
|
+
gl.uniform1f(display.colorCount, 3);
|
|
1181
|
+
gl.uniform1f(display.proportion, p.proportion / 100);
|
|
1182
|
+
gl.uniform1f(display.softness, p.softness / 100);
|
|
1183
|
+
gl.uniform1f(display.shape, 0);
|
|
1184
|
+
gl.uniform1f(display.shapeScale, p.shapeScale / 100);
|
|
1185
|
+
gl.uniform1f(display.distortion, p.distortion / 100);
|
|
1186
|
+
gl.uniform1f(display.swirl, p.swirl / 50);
|
|
1187
|
+
gl.uniform1f(display.swirlIterations, p.swirlIterations);
|
|
1188
|
+
gl.uniform1f(display.distortBoost, p.distortBoost);
|
|
1189
|
+
gl.uniform1f(display.noiseBoost, p.noiseBoost);
|
|
1190
|
+
gl.uniform1f(display.swirlBoost, p.swirlBoost);
|
|
1191
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
1192
|
+
};
|
|
1193
|
+
const handle = {
|
|
1194
|
+
setParams: (next) => {
|
|
1195
|
+
current = { ...next };
|
|
1196
|
+
},
|
|
1197
|
+
stir: (x, y, vx, vy) => {
|
|
1198
|
+
pointer.x += (x - pointer.x) * 0.35;
|
|
1199
|
+
pointer.y += (y - pointer.y) * 0.35;
|
|
1200
|
+
pointer.svx += (vx - pointer.svx) * 0.3;
|
|
1201
|
+
pointer.svy += (vy - pointer.svy) * 0.3;
|
|
1202
|
+
},
|
|
1203
|
+
dispose: () => {
|
|
1204
|
+
cancelAnimationFrame(raf);
|
|
1205
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
1209
|
+
frame(performance.now());
|
|
1210
|
+
cancelAnimationFrame(raf);
|
|
1211
|
+
return handle;
|
|
1212
|
+
}
|
|
1213
|
+
raf = requestAnimationFrame(frame);
|
|
1214
|
+
return handle;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
// src/client/fluid-tones.ts
|
|
1218
|
+
function hsl(h, s, l) {
|
|
1219
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
1220
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
1221
|
+
const m = l - c / 2;
|
|
1222
|
+
let r = 0;
|
|
1223
|
+
let g = 0;
|
|
1224
|
+
let b = 0;
|
|
1225
|
+
if (h < 60) {
|
|
1226
|
+
r = c;
|
|
1227
|
+
g = x;
|
|
1228
|
+
} else if (h < 120) {
|
|
1229
|
+
r = x;
|
|
1230
|
+
g = c;
|
|
1231
|
+
} else if (h < 180) {
|
|
1232
|
+
g = c;
|
|
1233
|
+
b = x;
|
|
1234
|
+
} else if (h < 240) {
|
|
1235
|
+
g = x;
|
|
1236
|
+
b = c;
|
|
1237
|
+
} else if (h < 300) {
|
|
1238
|
+
r = x;
|
|
1239
|
+
b = c;
|
|
1240
|
+
} else {
|
|
1241
|
+
r = c;
|
|
1242
|
+
b = x;
|
|
1243
|
+
}
|
|
1244
|
+
const toHex = (v) => Math.round((v + m) * 255).toString(16).padStart(2, "0");
|
|
1245
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1246
|
+
}
|
|
1247
|
+
var HUE_BASE = 217;
|
|
1248
|
+
function fluidToneColors(dark, hue, depth) {
|
|
1249
|
+
const h = ((hue + HUE_BASE) % 360 + 360) % 360;
|
|
1250
|
+
const d = Math.min(1, Math.max(0, depth / 100));
|
|
1251
|
+
const ramp = (deep, mid, pale) => d < 0.5 ? deep + (mid - deep) * d / 0.5 : mid + (pale - mid) * (d - 0.5) / 0.5;
|
|
1252
|
+
if (dark) {
|
|
1253
|
+
return {
|
|
1254
|
+
color1: hsl(h, 0.85, ramp(0, 0.46, 0.62)),
|
|
1255
|
+
color2: hsl(h, 0.9, ramp(0, 0.305, 0.45)),
|
|
1256
|
+
color3: hsl(h, 0.5, ramp(0, 0.075, 0.1))
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
return {
|
|
1260
|
+
color1: hsl(h, 1, ramp(0.27, 0.45, 0.9)),
|
|
1261
|
+
color2: hsl(h, 0.55, 0.86),
|
|
1262
|
+
color3: hsl(h, 0.25, 0.955)
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// src/client/fluid-interactions.ts
|
|
1267
|
+
function uv(canvas, clientX, clientY) {
|
|
1268
|
+
const rect = canvas.getBoundingClientRect();
|
|
1269
|
+
return {
|
|
1270
|
+
x: rect.width <= 0 ? 0.5 : (clientX - rect.left) / rect.width,
|
|
1271
|
+
y: rect.height <= 0 ? 0.5 : 1 - (clientY - rect.top) / rect.height
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
function attachFluidInteractions(targets) {
|
|
1275
|
+
const { main, mainCanvas } = targets;
|
|
1276
|
+
const lastStir = /* @__PURE__ */ new WeakMap();
|
|
1277
|
+
const ripples = /* @__PURE__ */ new Set();
|
|
1278
|
+
const stirButton = (button, strength) => {
|
|
1279
|
+
const now = performance.now();
|
|
1280
|
+
const previous = lastStir.get(button) ?? 0;
|
|
1281
|
+
if (now - previous < 160) return;
|
|
1282
|
+
lastStir.set(button, now);
|
|
1283
|
+
const rect = button.getBoundingClientRect();
|
|
1284
|
+
const point = uv(mainCanvas, rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
1285
|
+
main.stir(point.x, point.y, 0, -strength);
|
|
1286
|
+
};
|
|
1287
|
+
const ripple = (cx, cy) => {
|
|
1288
|
+
const rect = mainCanvas.getBoundingClientRect();
|
|
1289
|
+
if (rect.width <= 0 || rect.height <= 0) return;
|
|
1290
|
+
const ux = (cx - rect.left) / rect.width;
|
|
1291
|
+
const uy = 1 - (cy - rect.top) / rect.height;
|
|
1292
|
+
const start = performance.now();
|
|
1293
|
+
const duration = 1500;
|
|
1294
|
+
const maxRadius = 120;
|
|
1295
|
+
const count = 8;
|
|
1296
|
+
const step = () => {
|
|
1297
|
+
const t = performance.now() - start;
|
|
1298
|
+
if (t > duration) return;
|
|
1299
|
+
const k = t / duration;
|
|
1300
|
+
const radius = maxRadius * k * k;
|
|
1301
|
+
const strength = 0.05 * (1 - k);
|
|
1302
|
+
const spin = 0.4 * k;
|
|
1303
|
+
for (let i = 0; i < count; i += 1) {
|
|
1304
|
+
const angle = i / count * Math.PI * 2 + spin;
|
|
1305
|
+
const px = ux + radius * Math.cos(angle) / rect.width;
|
|
1306
|
+
const py = uy + radius * Math.sin(angle) / rect.height;
|
|
1307
|
+
main.stir(px, py, Math.cos(angle) * strength, -Math.sin(angle) * strength);
|
|
1308
|
+
}
|
|
1309
|
+
const id6 = requestAnimationFrame(step);
|
|
1310
|
+
ripples.add(id6);
|
|
1311
|
+
};
|
|
1312
|
+
const id5 = requestAnimationFrame(step);
|
|
1313
|
+
ripples.add(id5);
|
|
1314
|
+
};
|
|
1315
|
+
const onPointerOver = (event) => {
|
|
1316
|
+
const button = event.target?.closest?.("button");
|
|
1317
|
+
if (button !== void 0 && button !== null) stirButton(button, 0.04);
|
|
1318
|
+
};
|
|
1319
|
+
const onClick = (event) => {
|
|
1320
|
+
const button = event.target?.closest?.("button");
|
|
1321
|
+
if (button === void 0 || button === null) return;
|
|
1322
|
+
const now = performance.now();
|
|
1323
|
+
const previous = lastStir.get(button) ?? 0;
|
|
1324
|
+
if (now - previous < 500) return;
|
|
1325
|
+
lastStir.set(button, now);
|
|
1326
|
+
const rect = button.getBoundingClientRect();
|
|
1327
|
+
ripple(rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
1328
|
+
};
|
|
1329
|
+
document.addEventListener("pointerover", onPointerOver, { capture: true });
|
|
1330
|
+
document.addEventListener("click", onClick, { capture: true });
|
|
1331
|
+
return () => {
|
|
1332
|
+
for (const id5 of ripples) cancelAnimationFrame(id5);
|
|
1333
|
+
ripples.clear();
|
|
1334
|
+
document.removeEventListener("pointerover", onPointerOver, { capture: true });
|
|
1335
|
+
document.removeEventListener("click", onClick, { capture: true });
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// src/client/seam-stamper.ts
|
|
1340
|
+
var SEAMS = [
|
|
1341
|
+
// The layout frame: the sidebar column's direct parent.
|
|
1342
|
+
{ attribute: "data-dsh-frame", selector: ':has(> [class*="sidebarCol"])' },
|
|
1343
|
+
// The sidebar content root (topmost `root` under the column — settings
|
|
1344
|
+
// internals also carry a `root` class but sit deeper, so first match wins).
|
|
1345
|
+
{ attribute: "data-dsh-sidebar-root", selector: '[class*="sidebarCol"] [class*="root"]', first: true },
|
|
1346
|
+
// New-session button (the raised-surface seam).
|
|
1347
|
+
{ attribute: "data-dsh-surface", selector: 'button[class*="newSession"]' },
|
|
1348
|
+
// Trajectory view (the only composer-overlay view today).
|
|
1349
|
+
{ attribute: "data-dsh-trajectory", selector: "[data-conversation-composer-overlay]" },
|
|
1350
|
+
// Details panel (topmost `root` under the details column).
|
|
1351
|
+
{ attribute: "data-dsh-details", selector: '[class*="detailsCol"] [class*="root"]', first: true },
|
|
1352
|
+
// Composer bar root: the composer card's direct parent.
|
|
1353
|
+
{ attribute: "data-dsh-inputbar", selector: ":has(> [data-composer-card])" },
|
|
1354
|
+
// Composer attach "+" button.
|
|
1355
|
+
{ attribute: "data-dsh-add", selector: '[data-composer-card] [class*="add"]' },
|
|
1356
|
+
// Session stats line under the composer (composer.dock slot).
|
|
1357
|
+
{ attribute: "data-dsh-stats", selector: '[data-slot="conversation.composer.dock"] [class*="root"]' },
|
|
1358
|
+
// Spotlight / hover-tilt panes: the floating-glass surfaces the cursor
|
|
1359
|
+
// glow and the geometric press target. The inputbar (composer + its
|
|
1360
|
+
// docked stats band) is ONE spot so the fused piece tilts and glows
|
|
1361
|
+
// together; the small + bead and chat bubbles stay out so the effect
|
|
1362
|
+
// reads as "the glass panes", not every surface.
|
|
1363
|
+
{ attribute: "data-dsh-aqua-spot", selector: "header", first: true },
|
|
1364
|
+
{ attribute: "data-dsh-aqua-spot", selector: '[class*="sidebarCol"]', first: true },
|
|
1365
|
+
{ attribute: "data-dsh-aqua-spot", selector: "[data-dsh-inputbar]" },
|
|
1366
|
+
{ attribute: "data-dsh-aqua-spot", selector: "[data-dsh-trajectory]" },
|
|
1367
|
+
{ attribute: "data-dsh-aqua-spot", selector: "[data-dsh-surface]" },
|
|
1368
|
+
// The sidebar wordmark button (its badge plate gets the official pill).
|
|
1369
|
+
{ attribute: "data-dsh-wordmark", selector: '[class*="sidebarCol"] [class*="brand"]', first: true }
|
|
1370
|
+
];
|
|
1371
|
+
function stamp(seam) {
|
|
1372
|
+
if (seam.first) {
|
|
1373
|
+
const el = document.querySelector(seam.selector);
|
|
1374
|
+
if (el !== null && !el.hasAttribute(seam.attribute)) el.setAttribute(seam.attribute, "");
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
for (const el of document.querySelectorAll(seam.selector)) {
|
|
1378
|
+
if (!el.hasAttribute(seam.attribute)) el.setAttribute(seam.attribute, "");
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function stampAll() {
|
|
1382
|
+
for (const seam of SEAMS) stamp(seam);
|
|
1383
|
+
}
|
|
1384
|
+
function startSeamStamper() {
|
|
1385
|
+
stampAll();
|
|
1386
|
+
let sidebar = null;
|
|
1387
|
+
const updateFluidBounds = () => {
|
|
1388
|
+
const rect = sidebar?.getBoundingClientRect();
|
|
1389
|
+
document.documentElement.style.setProperty("--dsh-aqua-fluid-left", `${rect?.left ?? 0}px`);
|
|
1390
|
+
document.documentElement.style.setProperty("--dsh-aqua-fluid-width", `${rect?.width ?? 0}px`);
|
|
1391
|
+
};
|
|
1392
|
+
const resize = new ResizeObserver(updateFluidBounds);
|
|
1393
|
+
const refresh = () => {
|
|
1394
|
+
stampAll();
|
|
1395
|
+
const next = document.querySelector('[class*="sidebarCol"]');
|
|
1396
|
+
if (next !== sidebar) {
|
|
1397
|
+
resize.disconnect();
|
|
1398
|
+
sidebar = next;
|
|
1399
|
+
if (sidebar !== null) resize.observe(sidebar);
|
|
1400
|
+
}
|
|
1401
|
+
updateFluidBounds();
|
|
1402
|
+
};
|
|
1403
|
+
const headers = /* @__PURE__ */ new Map();
|
|
1404
|
+
const updateHeaderBounds = () => {
|
|
1405
|
+
for (const [header, phase] of headers) {
|
|
1406
|
+
const margin = Number.parseFloat(getComputedStyle(header).marginTop) || 0;
|
|
1407
|
+
const value = `${Math.ceil(header.offsetHeight + margin)}px`;
|
|
1408
|
+
if (phase.style.getPropertyValue("--dsh-aqua-header-overlap") !== value) {
|
|
1409
|
+
phase.style.setProperty("--dsh-aqua-header-overlap", value);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
};
|
|
1413
|
+
const headerResize = new ResizeObserver(updateHeaderBounds);
|
|
1414
|
+
const refreshHeaders = () => {
|
|
1415
|
+
const live = new Set(document.querySelectorAll("[data-phase] header"));
|
|
1416
|
+
for (const [header, phase] of headers) {
|
|
1417
|
+
if (!live.has(header)) {
|
|
1418
|
+
headerResize.unobserve(header);
|
|
1419
|
+
phase.style.removeProperty("--dsh-aqua-header-overlap");
|
|
1420
|
+
headers.delete(header);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
for (const header of live) {
|
|
1424
|
+
const phase = header.closest("[data-phase]");
|
|
1425
|
+
if (phase && !headers.has(header)) {
|
|
1426
|
+
headers.set(header, phase);
|
|
1427
|
+
headerResize.observe(header);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
updateHeaderBounds();
|
|
1431
|
+
};
|
|
1432
|
+
const refreshAll = () => {
|
|
1433
|
+
refresh();
|
|
1434
|
+
refreshHeaders();
|
|
1435
|
+
};
|
|
1436
|
+
refreshAll();
|
|
1437
|
+
const observer = new MutationObserver(refreshAll);
|
|
1438
|
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
1439
|
+
window.addEventListener("resize", updateFluidBounds);
|
|
1440
|
+
return () => {
|
|
1441
|
+
observer.disconnect();
|
|
1442
|
+
resize.disconnect();
|
|
1443
|
+
headerResize.disconnect();
|
|
1444
|
+
for (const phase of headers.values()) phase.style.removeProperty("--dsh-aqua-header-overlap");
|
|
1445
|
+
headers.clear();
|
|
1446
|
+
window.removeEventListener("resize", updateFluidBounds);
|
|
1447
|
+
document.documentElement.style.removeProperty("--dsh-aqua-fluid-left");
|
|
1448
|
+
document.documentElement.style.removeProperty("--dsh-aqua-fluid-width");
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
// src/client/whale.ts
|
|
1453
|
+
var WHALE_SVG = `<svg width="24" height="18" viewBox="0 0 24 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1454
|
+
<path d="M22.9168 1.43018C22.6713 1.31018 22.5658 1.53918 22.4223 1.65519C22.3733 1.69269 22.3318 1.74169 22.2903 1.78669C21.9317 2.1697 21.5127 2.42121 20.9657 2.39121C20.1657 2.34621 19.4827 2.59771 18.8787 3.20973C18.7502 2.45521 18.3236 2.0047 17.6746 1.71569C17.3351 1.56568 16.9916 1.41518 16.7536 1.08867C16.5876 0.856163 16.5421 0.597155 16.4591 0.341647C16.4061 0.187643 16.3536 0.0301382 16.1761 0.00363739C15.9836 -0.0263635 15.9081 0.135141 15.8326 0.270145C15.5306 0.822162 15.4136 1.43018 15.4251 2.0462C15.4516 3.43174 16.0366 4.53527 17.1991 5.3203C17.3311 5.4103 17.3651 5.5003 17.3236 5.63181C17.2441 5.90231 17.1501 6.16482 17.0671 6.43533C17.0141 6.60784 16.9351 6.64584 16.7501 6.57033C16.1121 6.30383 15.5611 5.90931 15.074 5.4328C14.2475 4.63328 13.5 3.75075 12.568 3.05973C12.349 2.89822 12.13 2.74822 11.9034 2.60522C10.9524 1.68169 12.028 0.923165 12.277 0.833162C12.5375 0.739159 12.3675 0.41615 11.5259 0.42015C10.6844 0.42365 9.91439 0.705658 8.93286 1.08117C8.78935 1.13767 8.63835 1.17867 8.48384 1.21267C7.59332 1.04367 6.66829 1.00617 5.70226 1.11517C3.88321 1.31768 2.43016 2.1777 1.36213 3.64575C0.0790928 5.4103 -0.222916 7.41536 0.146595 9.50642C0.535106 11.7105 1.66014 13.535 3.38869 14.9616C5.18125 16.4406 7.24581 17.1657 9.60138 17.0266C11.0319 16.9441 12.6245 16.7526 14.421 15.2321C14.874 15.4576 15.3496 15.5476 16.1381 15.6151C16.7456 15.6716 17.3306 15.5851 17.7836 15.4911C18.4931 15.3411 18.4441 14.6841 18.1876 14.5636C16.1081 13.595 16.5646 13.9891 16.1496 13.67C17.2061 12.42 18.8202 10.1979 19.3182 7.17235C19.3672 6.83834 19.4297 6.36783 19.4222 6.09732C19.4182 5.93231 19.4562 5.86831 19.6447 5.84931C20.1657 5.78931 20.6712 5.64681 21.1357 5.3913C22.4833 4.65528 23.0268 3.44624 23.1548 1.9972C23.1738 1.77569 23.1508 1.54668 22.9168 1.43018ZM11.1749 14.4736C9.15936 12.889 8.18184 12.3675 7.77832 12.39C7.40081 12.4125 7.46881 12.8445 7.55182 13.126C7.63882 13.404 7.75182 13.5955 7.91033 13.8396C8.01983 14.0011 8.09533 14.2411 7.80083 14.4216C7.15181 14.8231 6.02327 14.2866 5.97027 14.2601C4.65673 13.4865 3.5587 12.4655 2.78467 11.069C2.03715 9.72493 1.60314 8.28289 1.53164 6.74384C1.51264 6.37233 1.62214 6.24082 1.99215 6.17332C2.47916 6.08332 2.98118 6.06432 3.46769 6.13582C5.52476 6.43633 7.27581 7.35586 8.74385 8.8129C9.58188 9.64243 10.2159 10.634 10.8689 11.6025C11.5634 12.631 12.3105 13.611 13.262 14.4146C13.598 14.6961 13.866 14.9101 14.1225 15.0681C13.349 15.1546 12.058 15.1731 11.1749 14.4746V14.4736ZM12.141 8.25988C12.141 8.09488 12.273 7.96338 12.439 7.96338C12.4765 7.96338 12.5105 7.97088 12.541 7.98188C12.5825 7.99688 12.6205 8.01938 12.6505 8.05338C12.7035 8.10588 12.7335 8.18088 12.7335 8.25988C12.7335 8.42489 12.6015 8.55639 12.4355 8.55639C12.2695 8.55639 12.141 8.42489 12.141 8.25988ZM15.1415 9.79893C14.949 9.87793 14.7565 9.94544 14.5715 9.95294C14.2845 9.96794 13.9715 9.85143 13.8015 9.70893C13.5375 9.48742 13.3485 9.36342 13.2695 8.97691C13.2355 8.8119 13.2545 8.55639 13.2845 8.40989C13.3525 8.09438 13.277 7.89187 13.0545 7.70787C12.8735 7.55786 12.643 7.51636 12.39 7.51636C12.2955 7.51636 12.209 7.47486 12.1445 7.44136C12.039 7.38886 11.9519 7.25735 12.035 7.09585C12.0615 7.04335 12.19 6.91584 12.22 6.89334C12.5635 6.69784 12.9595 6.76184 13.326 6.90834C13.6655 7.04735 13.9225 7.30236 14.292 7.66287C14.6695 8.09838 14.7375 8.21838 14.9525 8.54539C15.1225 8.8009 15.277 9.06341 15.3831 9.36392C15.4471 9.55142 15.3641 9.70493 15.1415 9.79893Z" fill="#FFFFFF"/>
|
|
1455
|
+
</svg>`;
|
|
1456
|
+
var GRID = 60;
|
|
1457
|
+
var UNIT = 0.18;
|
|
1458
|
+
var LIGHT_X = 4.5;
|
|
1459
|
+
var LIGHT_Y = 5.5;
|
|
1460
|
+
var LIGHT_RANGE = 14;
|
|
1461
|
+
var SHADE_MIN = 0.2;
|
|
1462
|
+
var SHADE_MAX = 0.4 * 2.79;
|
|
1463
|
+
var FOLLOW_X = 1.05;
|
|
1464
|
+
var LOOSE = 1;
|
|
1465
|
+
var MOUSE_RADIUS = 4.9;
|
|
1466
|
+
var MOUSE_STRENGTH = 0.8;
|
|
1467
|
+
var MOUSE_DECAY = 0.2;
|
|
1468
|
+
var MOUSE_DISTORT = 5;
|
|
1469
|
+
var FPS = 30;
|
|
1470
|
+
var WORLD_H = 2 * 18 * Math.tan(50 * Math.PI / 360);
|
|
1471
|
+
function hash(n) {
|
|
1472
|
+
const s = Math.sin(n * 12.9898) * 43758.5453;
|
|
1473
|
+
return s - Math.floor(s) - 0.5;
|
|
1474
|
+
}
|
|
1475
|
+
function mountWhale(host, dark) {
|
|
1476
|
+
const holder = document.createElement("div");
|
|
1477
|
+
holder.setAttribute("data-dsh-aqua-whale", "");
|
|
1478
|
+
holder.setAttribute("data-scheme", dark ? "dark" : "light");
|
|
1479
|
+
const canvas = document.createElement("canvas");
|
|
1480
|
+
canvas.setAttribute("aria-hidden", "true");
|
|
1481
|
+
holder.appendChild(canvas);
|
|
1482
|
+
host.appendChild(holder);
|
|
1483
|
+
const ctx = canvas.getContext("2d");
|
|
1484
|
+
if (ctx === null) {
|
|
1485
|
+
holder.remove();
|
|
1486
|
+
return { setDark: () => {
|
|
1487
|
+
}, dispose: () => {
|
|
1488
|
+
} };
|
|
1489
|
+
}
|
|
1490
|
+
const reduced = typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1491
|
+
const particles = [];
|
|
1492
|
+
let raf = 0;
|
|
1493
|
+
let disposed = false;
|
|
1494
|
+
let startedAt = performance.now();
|
|
1495
|
+
let darkMode = dark;
|
|
1496
|
+
let mouseWorld = { x: 0, y: 0 };
|
|
1497
|
+
let dpr = 1;
|
|
1498
|
+
let scale = 1;
|
|
1499
|
+
let width = 0;
|
|
1500
|
+
let height = 0;
|
|
1501
|
+
const positionHost = () => {
|
|
1502
|
+
const phase = document.querySelector("[data-phase]");
|
|
1503
|
+
const rect = phase?.getBoundingClientRect();
|
|
1504
|
+
const r = rect !== void 0 && rect.width > 0 ? rect : { left: 0, top: 0, width: window.innerWidth, height: window.innerHeight };
|
|
1505
|
+
const size = Math.round(Math.max(220, Math.min(660, window.innerHeight * 0.76, r.width * 0.8)));
|
|
1506
|
+
const left = Math.round(r.left + r.width / 2);
|
|
1507
|
+
const top = Math.round(r.top + r.height / 2);
|
|
1508
|
+
if (holder.style.width !== `${size}px`) holder.style.width = `${size}px`;
|
|
1509
|
+
if (holder.style.height !== `${size}px`) holder.style.height = `${size}px`;
|
|
1510
|
+
if (holder.style.left !== `${left}px`) holder.style.left = `${left}px`;
|
|
1511
|
+
if (holder.style.top !== `${top}px`) holder.style.top = `${top}px`;
|
|
1512
|
+
};
|
|
1513
|
+
const resize = () => {
|
|
1514
|
+
positionHost();
|
|
1515
|
+
const rect = holder.getBoundingClientRect();
|
|
1516
|
+
width = Math.max(1, rect.width);
|
|
1517
|
+
height = Math.max(1, rect.height);
|
|
1518
|
+
dpr = Math.min(window.devicePixelRatio || 1, 1.5);
|
|
1519
|
+
canvas.width = Math.max(1, Math.round(width * dpr));
|
|
1520
|
+
canvas.height = Math.max(1, Math.round(height * dpr));
|
|
1521
|
+
scale = height / WORLD_H;
|
|
1522
|
+
};
|
|
1523
|
+
const sample = (img2) => {
|
|
1524
|
+
const off = document.createElement("canvas");
|
|
1525
|
+
off.width = GRID;
|
|
1526
|
+
off.height = GRID;
|
|
1527
|
+
const octx = off.getContext("2d");
|
|
1528
|
+
if (octx === null) return;
|
|
1529
|
+
octx.fillStyle = "#000";
|
|
1530
|
+
octx.fillRect(0, 0, GRID, GRID);
|
|
1531
|
+
const fit = Math.min(GRID / img2.width, GRID / img2.height);
|
|
1532
|
+
const w = img2.width * fit;
|
|
1533
|
+
const h = img2.height * fit;
|
|
1534
|
+
octx.drawImage(img2, (GRID - w) / 2, (GRID - h) / 2, w, h);
|
|
1535
|
+
const data = octx.getImageData(0, 0, GRID, GRID).data;
|
|
1536
|
+
const lum = new Float32Array(GRID * GRID);
|
|
1537
|
+
for (let i = 0; i < GRID * GRID; i++) {
|
|
1538
|
+
lum[i] = (0.299 * data[4 * i] + 0.587 * data[4 * i + 1] + 0.114 * data[4 * i + 2]) / 255;
|
|
1539
|
+
}
|
|
1540
|
+
const hasBrightNeighbor = (x, y) => {
|
|
1541
|
+
for (let dy = -2; dy <= 2; dy++) {
|
|
1542
|
+
for (let dx = -2; dx <= 2; dx++) {
|
|
1543
|
+
if (dx === 0 && dy === 0) continue;
|
|
1544
|
+
const nx = x + dx;
|
|
1545
|
+
const ny = y + dy;
|
|
1546
|
+
if (nx < 0 || ny < 0 || nx >= GRID || ny >= GRID) continue;
|
|
1547
|
+
if (lum[ny * GRID + nx] > 0.2) return true;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return false;
|
|
1551
|
+
};
|
|
1552
|
+
for (let e = 0; e < GRID; e++) {
|
|
1553
|
+
for (let n = 0; n < GRID; n++) {
|
|
1554
|
+
const a = lum[e * GRID + n];
|
|
1555
|
+
if (a <= 0.2 || !hasBrightNeighbor(n, e)) continue;
|
|
1556
|
+
const x = (n - GRID / 2) * UNIT;
|
|
1557
|
+
const y = (GRID / 2 - e) * UNIT;
|
|
1558
|
+
let edge = 0;
|
|
1559
|
+
for (let dy = -1; dy <= 1; dy++) {
|
|
1560
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
1561
|
+
if (dx === 0 && dy === 0) continue;
|
|
1562
|
+
const nx = n + dx;
|
|
1563
|
+
const ny = e + dy;
|
|
1564
|
+
if (nx < 0 || ny < 0 || nx >= GRID || ny >= GRID || lum[ny * GRID + nx] <= 0.2) edge++;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
const phi = Math.random() * Math.PI * 2;
|
|
1568
|
+
const theta = Math.acos(2 * Math.random() - 1);
|
|
1569
|
+
const rad = 3 * (0.4 + 0.6 * Math.random());
|
|
1570
|
+
particles.push({
|
|
1571
|
+
x,
|
|
1572
|
+
y,
|
|
1573
|
+
opacity: a,
|
|
1574
|
+
edge: edge / 8,
|
|
1575
|
+
sx: Math.sin(theta) * Math.cos(phi) * rad,
|
|
1576
|
+
sy: Math.sin(theta) * Math.sin(phi) * rad,
|
|
1577
|
+
sz: Math.cos(theta) * rad * 0.5
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
const draw = (assembly, time) => {
|
|
1583
|
+
if (width === 0 || height === 0) resize();
|
|
1584
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
1585
|
+
ctx.clearRect(0, 0, width, height);
|
|
1586
|
+
ctx.globalCompositeOperation = "lighter";
|
|
1587
|
+
const targetX = mouseWorld.x;
|
|
1588
|
+
const targetY = mouseWorld.y;
|
|
1589
|
+
const lightX = LIGHT_X + targetX * FOLLOW_X;
|
|
1590
|
+
const lightY = LIGHT_Y;
|
|
1591
|
+
const mouseRadius = MOUSE_RADIUS;
|
|
1592
|
+
const strength = MOUSE_STRENGTH;
|
|
1593
|
+
const size = Math.max(1.1, 0.06 * scale * dpr);
|
|
1594
|
+
const breathe = 0.15 * Math.sin(0.4 * time);
|
|
1595
|
+
for (let i = 0; i < particles.length; i++) {
|
|
1596
|
+
const p = particles[i];
|
|
1597
|
+
const loose = LOOSE * (0.25 + 0.75 * p.edge) * assembly;
|
|
1598
|
+
let px = p.x + hash(i) * 0.05 * loose;
|
|
1599
|
+
let py = p.y + hash(i * 1.37 + 7) * 0.05 * loose;
|
|
1600
|
+
px += Math.sin(time * 0.5 + i * 0.53) * 0.06 * loose;
|
|
1601
|
+
py += Math.cos(time * 0.42 + i * 0.71) * 0.06 * loose;
|
|
1602
|
+
const tail = smoothstep(0.5, 4.5, p.x) * LOOSE * assembly;
|
|
1603
|
+
py += Math.sin(time * 1.1 - p.x * 0.7) * 0.1 * tail;
|
|
1604
|
+
px += Math.cos(time * 0.9 - p.x * 0.55) * 0.06 * tail;
|
|
1605
|
+
px = p.sx + (px - p.sx) * assembly;
|
|
1606
|
+
py = p.sy + (py - p.sy) * assembly;
|
|
1607
|
+
if (assembly > 0.8) {
|
|
1608
|
+
const mouseEffect = (assembly - 0.8) * 5;
|
|
1609
|
+
const mx = px - targetX;
|
|
1610
|
+
const my = py - targetY;
|
|
1611
|
+
const dist2 = Math.sqrt(mx * mx + my * my);
|
|
1612
|
+
if (dist2 < mouseRadius && dist2 > 1e-3) {
|
|
1613
|
+
const t = 1 - dist2 / mouseRadius;
|
|
1614
|
+
const force = t * t * t * mouseEffect * strength;
|
|
1615
|
+
const angle = Math.sin(i * 0.37 + time * 0.5) * MOUSE_DISTORT;
|
|
1616
|
+
const ca = Math.cos(angle);
|
|
1617
|
+
const sa = Math.sin(angle);
|
|
1618
|
+
const ux = mx / dist2;
|
|
1619
|
+
const uy = my / dist2;
|
|
1620
|
+
const rx = ux * ca - uy * sa;
|
|
1621
|
+
const ry = ux * sa + uy * ca;
|
|
1622
|
+
px += rx * force * 2;
|
|
1623
|
+
py += ry * force * 2;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
const ldx = px - lightX;
|
|
1627
|
+
const ldy = py - lightY;
|
|
1628
|
+
const lit = Math.min(1, Math.max(0, 1 - Math.sqrt(ldx * ldx + ldy * ldy) / LIGHT_RANGE));
|
|
1629
|
+
const vLight = SHADE_MIN + SHADE_MAX * lit * lit;
|
|
1630
|
+
const dist = Math.sqrt(px * px + py * py);
|
|
1631
|
+
const glow = smoothstep(8, 0, dist) * 0.3 * assembly;
|
|
1632
|
+
const baseAlpha = 0.45 + 0.3 * assembly;
|
|
1633
|
+
const shimmer = Math.sin(time * 1.5 + px * 5 + py * 3) * 0.1 + 0.9;
|
|
1634
|
+
const alpha = p.opacity * (baseAlpha + glow) * shimmer * Math.min(vLight, 1);
|
|
1635
|
+
const br = darkMode ? 0.75 : 0.42;
|
|
1636
|
+
const bg = darkMode ? 0.8 : 0.44;
|
|
1637
|
+
const bb = darkMode ? 0.9 : 0.47;
|
|
1638
|
+
const r = Math.min(255, Math.round((br * assembly + glow * 0.2) * vLight * 255));
|
|
1639
|
+
const g = Math.min(255, Math.round((bg * assembly + glow * 0.3) * vLight * 255));
|
|
1640
|
+
const b = Math.min(255, Math.round((bb * assembly + glow * 0.5) * vLight * 255));
|
|
1641
|
+
if (alpha <= 4e-3) continue;
|
|
1642
|
+
ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${alpha.toFixed(3)})`;
|
|
1643
|
+
const sx = width / 2 + px * scale - size / 2;
|
|
1644
|
+
const sy = height / 2 - (py + breathe) * scale - size / 2;
|
|
1645
|
+
ctx.fillRect(sx, sy, size, size);
|
|
1646
|
+
}
|
|
1647
|
+
ctx.globalCompositeOperation = "source-over";
|
|
1648
|
+
};
|
|
1649
|
+
function smoothstep(a, b, t) {
|
|
1650
|
+
const x = Math.min(1, Math.max(0, (t - a) / (b - a)));
|
|
1651
|
+
return x * x * (3 - 2 * x);
|
|
1652
|
+
}
|
|
1653
|
+
let mouseNdc = { x: 0, y: 0 };
|
|
1654
|
+
const onMove = (event) => {
|
|
1655
|
+
const rect = holder.getBoundingClientRect();
|
|
1656
|
+
if (rect.width === 0 || rect.height === 0) return;
|
|
1657
|
+
mouseNdc = {
|
|
1658
|
+
x: (event.clientX - rect.left) / rect.width * 2 - 1,
|
|
1659
|
+
y: -((event.clientY - rect.top) / rect.height * 2 - 1)
|
|
1660
|
+
};
|
|
1661
|
+
};
|
|
1662
|
+
window.addEventListener("pointermove", onMove, { passive: true });
|
|
1663
|
+
const start = () => {
|
|
1664
|
+
if (disposed) return;
|
|
1665
|
+
let last = performance.now();
|
|
1666
|
+
const step = (now) => {
|
|
1667
|
+
if (disposed) return;
|
|
1668
|
+
if (now - last < 1e3 / FPS) {
|
|
1669
|
+
raf = requestAnimationFrame(step);
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
last = now - (now - last) % (1e3 / FPS);
|
|
1673
|
+
positionHost();
|
|
1674
|
+
const elapsed = (now - startedAt) / 1e3;
|
|
1675
|
+
const raw = Math.min(1, Math.max(0, (elapsed - 0.3) / 2.5));
|
|
1676
|
+
const D = 1 - Math.pow(1 - raw, 3);
|
|
1677
|
+
const assembly = smoothstep(0, 1, D);
|
|
1678
|
+
const targetX = mouseNdc.x * WORLD_H / 2;
|
|
1679
|
+
const targetY = mouseNdc.y * WORLD_H / 2;
|
|
1680
|
+
mouseWorld.x += (targetX - mouseWorld.x) * MOUSE_DECAY;
|
|
1681
|
+
mouseWorld.y += (targetY - mouseWorld.y) * MOUSE_DECAY;
|
|
1682
|
+
draw(assembly, elapsed);
|
|
1683
|
+
raf = requestAnimationFrame(step);
|
|
1684
|
+
};
|
|
1685
|
+
raf = requestAnimationFrame(step);
|
|
1686
|
+
};
|
|
1687
|
+
resize();
|
|
1688
|
+
window.addEventListener("resize", resize);
|
|
1689
|
+
const img = new Image();
|
|
1690
|
+
img.onload = () => {
|
|
1691
|
+
if (disposed) return;
|
|
1692
|
+
sample(img);
|
|
1693
|
+
resize();
|
|
1694
|
+
if (reduced) {
|
|
1695
|
+
mouseWorld = { x: 0, y: 0 };
|
|
1696
|
+
draw(1, 2);
|
|
1697
|
+
window.setTimeout(() => {
|
|
1698
|
+
if (disposed) return;
|
|
1699
|
+
resize();
|
|
1700
|
+
draw(1, 2);
|
|
1701
|
+
}, 600);
|
|
1702
|
+
} else {
|
|
1703
|
+
start();
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(WHALE_SVG)}`;
|
|
1707
|
+
return {
|
|
1708
|
+
setDark: (dark2) => {
|
|
1709
|
+
if (darkMode === dark2) return;
|
|
1710
|
+
darkMode = dark2;
|
|
1711
|
+
holder.setAttribute("data-scheme", dark2 ? "dark" : "light");
|
|
1712
|
+
if (reduced && particles.length > 0) draw(1, 2);
|
|
1713
|
+
},
|
|
1714
|
+
dispose: () => {
|
|
1715
|
+
disposed = true;
|
|
1716
|
+
cancelAnimationFrame(raf);
|
|
1717
|
+
window.removeEventListener("pointermove", onMove);
|
|
1718
|
+
window.removeEventListener("resize", resize);
|
|
1719
|
+
holder.remove();
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
// src/client/mesh.ts
|
|
1725
|
+
var SPACING = 90;
|
|
1726
|
+
var REPEL_RADIUS = 140;
|
|
1727
|
+
var REPEL_FORCE = 30;
|
|
1728
|
+
var SPRING = 0.05;
|
|
1729
|
+
var DAMPING = 0.85;
|
|
1730
|
+
var LINE_GAP = 10;
|
|
1731
|
+
var MIN_LINE_DIST = 20;
|
|
1732
|
+
var LINE_COLOR = "rgba(60, 100, 160, ";
|
|
1733
|
+
var DOT_COLOR = "rgba(60, 100, 160, ";
|
|
1734
|
+
var LINE_ALPHA = 0.15;
|
|
1735
|
+
var DOT_ALPHA = 0.3;
|
|
1736
|
+
var FPS2 = 30;
|
|
1737
|
+
function mountMesh(host) {
|
|
1738
|
+
const canvas = document.createElement("canvas");
|
|
1739
|
+
canvas.setAttribute("data-dsh-aqua-mesh", "");
|
|
1740
|
+
canvas.setAttribute("aria-hidden", "true");
|
|
1741
|
+
host.appendChild(canvas);
|
|
1742
|
+
const ctx = canvas.getContext("2d");
|
|
1743
|
+
if (ctx === null) {
|
|
1744
|
+
canvas.remove();
|
|
1745
|
+
return { dispose: () => {
|
|
1746
|
+
} };
|
|
1747
|
+
}
|
|
1748
|
+
const reduced = typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1749
|
+
const coarse = typeof matchMedia !== "undefined" && matchMedia("(hover: none), (pointer: coarse)").matches;
|
|
1750
|
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
1751
|
+
let dots = [];
|
|
1752
|
+
let cols = 0;
|
|
1753
|
+
let rows = 0;
|
|
1754
|
+
let w = 0;
|
|
1755
|
+
let h = 0;
|
|
1756
|
+
let raf = 0;
|
|
1757
|
+
let disposed = false;
|
|
1758
|
+
let idle = false;
|
|
1759
|
+
let visible = true;
|
|
1760
|
+
let resizeTimer = 0;
|
|
1761
|
+
const mouse = { x: NaN, y: NaN };
|
|
1762
|
+
const build = () => {
|
|
1763
|
+
cols = Math.ceil(w / SPACING) + 1;
|
|
1764
|
+
rows = Math.ceil(h / SPACING) + 1;
|
|
1765
|
+
const startX = (w - (cols - 1) * SPACING) / 2;
|
|
1766
|
+
const startY = (h - (rows - 1) * SPACING) / 2;
|
|
1767
|
+
dots = [];
|
|
1768
|
+
for (let ry = 0; ry < rows; ry++) {
|
|
1769
|
+
for (let rx = 0; rx < cols; rx++) {
|
|
1770
|
+
const x = startX + SPACING * rx;
|
|
1771
|
+
const y = startY + SPACING * ry;
|
|
1772
|
+
dots.push({ restX: x, restY: y, x, y, vx: 0, vy: 0 });
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
const resize = () => {
|
|
1777
|
+
const cw = canvas.clientWidth;
|
|
1778
|
+
const ch = canvas.clientHeight;
|
|
1779
|
+
if (cw === w && ch === h) return;
|
|
1780
|
+
w = cw;
|
|
1781
|
+
h = ch;
|
|
1782
|
+
canvas.width = Math.max(1, Math.round(w * dpr));
|
|
1783
|
+
canvas.height = Math.max(1, Math.round(h * dpr));
|
|
1784
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
1785
|
+
window.clearTimeout(resizeTimer);
|
|
1786
|
+
resizeTimer = window.setTimeout(build, 150);
|
|
1787
|
+
};
|
|
1788
|
+
resize();
|
|
1789
|
+
build();
|
|
1790
|
+
const wake = () => {
|
|
1791
|
+
if (!idle) return;
|
|
1792
|
+
idle = false;
|
|
1793
|
+
if (raf === 0) raf = requestAnimationFrame(frame);
|
|
1794
|
+
};
|
|
1795
|
+
const onMove = (event) => {
|
|
1796
|
+
if (reduced || coarse) return;
|
|
1797
|
+
mouse.x = event.clientX;
|
|
1798
|
+
mouse.y = event.clientY;
|
|
1799
|
+
wake();
|
|
1800
|
+
};
|
|
1801
|
+
if (!reduced && !coarse) window.addEventListener("pointermove", onMove, { passive: true });
|
|
1802
|
+
let last = 0;
|
|
1803
|
+
const frame = (now) => {
|
|
1804
|
+
raf = 0;
|
|
1805
|
+
if (disposed) return;
|
|
1806
|
+
if (!visible || now - last < 1e3 / FPS2) {
|
|
1807
|
+
raf = requestAnimationFrame(frame);
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
last = now - (now - last) % (1e3 / FPS2);
|
|
1811
|
+
const cw = canvas.clientWidth;
|
|
1812
|
+
const ch = canvas.clientHeight;
|
|
1813
|
+
if (cw !== w || ch !== h) resize();
|
|
1814
|
+
ctx.clearRect(0, 0, w, h);
|
|
1815
|
+
const mx = mouse.x;
|
|
1816
|
+
const my = mouse.y;
|
|
1817
|
+
let maxV = 0;
|
|
1818
|
+
for (const dot of dots) {
|
|
1819
|
+
if (!Number.isNaN(mx) && !Number.isNaN(my)) {
|
|
1820
|
+
const dx = dot.x - mx;
|
|
1821
|
+
const dy = dot.y - my;
|
|
1822
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
1823
|
+
if (dist < REPEL_RADIUS && dist > 0.1) {
|
|
1824
|
+
const force = (1 - dist / REPEL_RADIUS) * REPEL_FORCE;
|
|
1825
|
+
const nx = dx / dist;
|
|
1826
|
+
const ny = dy / dist;
|
|
1827
|
+
dot.vx += nx * force * 0.1;
|
|
1828
|
+
dot.vy += ny * force * 0.1;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
const sx = dot.restX - dot.x;
|
|
1832
|
+
const sy = dot.restY - dot.y;
|
|
1833
|
+
dot.vx += SPRING * sx;
|
|
1834
|
+
dot.vy += SPRING * sy;
|
|
1835
|
+
dot.vx *= DAMPING;
|
|
1836
|
+
dot.vy *= DAMPING;
|
|
1837
|
+
dot.x += dot.vx;
|
|
1838
|
+
dot.y += dot.vy;
|
|
1839
|
+
const v = Math.abs(dot.vx) + Math.abs(dot.vy);
|
|
1840
|
+
if (v > maxV) maxV = v;
|
|
1841
|
+
}
|
|
1842
|
+
ctx.strokeStyle = `${LINE_COLOR}${LINE_ALPHA})`;
|
|
1843
|
+
ctx.lineWidth = 0.5;
|
|
1844
|
+
for (let ry = 0; ry < rows; ry++) {
|
|
1845
|
+
for (let rx = 0; rx < cols - 1; rx++) {
|
|
1846
|
+
const a = dots[ry * cols + rx];
|
|
1847
|
+
const b = dots[ry * cols + rx + 1];
|
|
1848
|
+
const dx = b.x - a.x;
|
|
1849
|
+
const dy = b.y - a.y;
|
|
1850
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
1851
|
+
if (dist < MIN_LINE_DIST) continue;
|
|
1852
|
+
const ux = dx / dist;
|
|
1853
|
+
const uy = dy / dist;
|
|
1854
|
+
ctx.beginPath();
|
|
1855
|
+
ctx.moveTo(a.x + LINE_GAP * ux, a.y + LINE_GAP * uy);
|
|
1856
|
+
ctx.lineTo(b.x - LINE_GAP * ux, b.y - LINE_GAP * uy);
|
|
1857
|
+
ctx.stroke();
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
for (let ry = 0; ry < rows - 1; ry++) {
|
|
1861
|
+
for (let rx = 0; rx < cols; rx++) {
|
|
1862
|
+
const a = dots[ry * cols + rx];
|
|
1863
|
+
const b = dots[(ry + 1) * cols + rx];
|
|
1864
|
+
const dx = b.x - a.x;
|
|
1865
|
+
const dy = b.y - a.y;
|
|
1866
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
1867
|
+
if (dist < MIN_LINE_DIST) continue;
|
|
1868
|
+
const ux = dx / dist;
|
|
1869
|
+
const uy = dy / dist;
|
|
1870
|
+
ctx.beginPath();
|
|
1871
|
+
ctx.moveTo(a.x + LINE_GAP * ux, a.y + LINE_GAP * uy);
|
|
1872
|
+
ctx.lineTo(b.x - LINE_GAP * ux, b.y - LINE_GAP * uy);
|
|
1873
|
+
ctx.stroke();
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
ctx.fillStyle = `${DOT_COLOR}1)`;
|
|
1877
|
+
for (const dot of dots) {
|
|
1878
|
+
let r = 1.8;
|
|
1879
|
+
let alpha = DOT_ALPHA;
|
|
1880
|
+
if (!Number.isNaN(mx) && !Number.isNaN(my)) {
|
|
1881
|
+
const dx = dot.x - mx;
|
|
1882
|
+
const dy = dot.y - my;
|
|
1883
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
1884
|
+
const near = Math.max(0, 1 - dist / REPEL_RADIUS);
|
|
1885
|
+
r = 1.8 + 2 * near;
|
|
1886
|
+
alpha = DOT_ALPHA + 0.4 * near;
|
|
1887
|
+
}
|
|
1888
|
+
ctx.globalAlpha = alpha;
|
|
1889
|
+
const size = 2 * r;
|
|
1890
|
+
ctx.fillRect(dot.x - r, dot.y - r, size, size);
|
|
1891
|
+
}
|
|
1892
|
+
ctx.globalAlpha = 1;
|
|
1893
|
+
if (maxV < 0.01) {
|
|
1894
|
+
idle = true;
|
|
1895
|
+
} else {
|
|
1896
|
+
raf = requestAnimationFrame(frame);
|
|
1897
|
+
}
|
|
1898
|
+
};
|
|
1899
|
+
if (reduced || coarse) {
|
|
1900
|
+
resize();
|
|
1901
|
+
ctx.clearRect(0, 0, w, h);
|
|
1902
|
+
ctx.strokeStyle = `${LINE_COLOR}${LINE_ALPHA})`;
|
|
1903
|
+
ctx.lineWidth = 0.5;
|
|
1904
|
+
for (let ry = 0; ry < rows; ry++) {
|
|
1905
|
+
for (let rx = 0; rx < cols - 1; rx++) {
|
|
1906
|
+
const a = dots[ry * cols + rx];
|
|
1907
|
+
const b = dots[ry * cols + rx + 1];
|
|
1908
|
+
ctx.beginPath();
|
|
1909
|
+
ctx.moveTo(a.x + LINE_GAP, a.y);
|
|
1910
|
+
ctx.lineTo(b.x - LINE_GAP, b.y);
|
|
1911
|
+
ctx.stroke();
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
for (let ry = 0; ry < rows - 1; ry++) {
|
|
1915
|
+
for (let rx = 0; rx < cols; rx++) {
|
|
1916
|
+
const a = dots[ry * cols + rx];
|
|
1917
|
+
const b = dots[(ry + 1) * cols + rx];
|
|
1918
|
+
ctx.beginPath();
|
|
1919
|
+
ctx.moveTo(a.x, a.y + LINE_GAP);
|
|
1920
|
+
ctx.lineTo(b.x, b.y - LINE_GAP);
|
|
1921
|
+
ctx.stroke();
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
ctx.fillStyle = `${DOT_COLOR}${DOT_ALPHA})`;
|
|
1925
|
+
for (const dot of dots) ctx.fillRect(dot.x - 1.8, dot.y - 1.8, 3.6, 3.6);
|
|
1926
|
+
} else {
|
|
1927
|
+
raf = requestAnimationFrame(frame);
|
|
1928
|
+
const observer = new IntersectionObserver(([entry]) => {
|
|
1929
|
+
visible = entry.isIntersecting;
|
|
1930
|
+
if (visible) wake();
|
|
1931
|
+
}, { threshold: 0 });
|
|
1932
|
+
observer.observe(canvas);
|
|
1933
|
+
return {
|
|
1934
|
+
dispose: () => {
|
|
1935
|
+
disposed = true;
|
|
1936
|
+
cancelAnimationFrame(raf);
|
|
1937
|
+
window.clearTimeout(resizeTimer);
|
|
1938
|
+
observer.disconnect();
|
|
1939
|
+
window.removeEventListener("pointermove", onMove);
|
|
1940
|
+
canvas.remove();
|
|
1941
|
+
}
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
return {
|
|
1945
|
+
dispose: () => {
|
|
1946
|
+
disposed = true;
|
|
1947
|
+
cancelAnimationFrame(raf);
|
|
1948
|
+
window.clearTimeout(resizeTimer);
|
|
1949
|
+
window.removeEventListener("pointermove", onMove);
|
|
1950
|
+
canvas.remove();
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
// src/client/spot-core.ts
|
|
1956
|
+
var SPOT_ATTR = "data-dsh-aqua-spot";
|
|
1957
|
+
var GLOW_ATTR = "data-dsh-aqua-glow";
|
|
1958
|
+
var ON_ATTR = "data-spot-on";
|
|
1959
|
+
var SPOT_SELECTOR = `[${SPOT_ATTR}]`;
|
|
1960
|
+
function closestSpot(target) {
|
|
1961
|
+
return target instanceof Element ? target.closest(SPOT_SELECTOR) : null;
|
|
1962
|
+
}
|
|
1963
|
+
function spotElements() {
|
|
1964
|
+
return Array.from(document.querySelectorAll(SPOT_SELECTOR));
|
|
1965
|
+
}
|
|
1966
|
+
function visualRect(spot) {
|
|
1967
|
+
if (spot.querySelector("[data-composer-card]") !== null) {
|
|
1968
|
+
const card = spot.querySelector("[data-composer-card]");
|
|
1969
|
+
const r0 = card.getBoundingClientRect();
|
|
1970
|
+
const stats = spot.querySelector("[data-dsh-stats]");
|
|
1971
|
+
if (stats === null) return r0;
|
|
1972
|
+
const r1 = stats.getBoundingClientRect();
|
|
1973
|
+
const left = Math.min(r0.left, r1.left);
|
|
1974
|
+
const top = Math.min(r0.top, r1.top);
|
|
1975
|
+
return new DOMRect(left, top, Math.max(r0.right, r1.right) - left, Math.max(r0.bottom, r1.bottom) - top);
|
|
1976
|
+
}
|
|
1977
|
+
return spot.getBoundingClientRect();
|
|
1978
|
+
}
|
|
1979
|
+
function inside(visual, clientX, clientY) {
|
|
1980
|
+
return clientX >= visual.left && clientX <= visual.right && clientY >= visual.top && clientY <= visual.bottom;
|
|
1981
|
+
}
|
|
1982
|
+
function localTopLeft(el, ancestor) {
|
|
1983
|
+
let x = 0;
|
|
1984
|
+
let y = 0;
|
|
1985
|
+
let node = el;
|
|
1986
|
+
while (node !== null && node !== ancestor) {
|
|
1987
|
+
x += node.offsetLeft;
|
|
1988
|
+
y += node.offsetTop;
|
|
1989
|
+
node = node.offsetParent;
|
|
1990
|
+
}
|
|
1991
|
+
return { x, y };
|
|
1992
|
+
}
|
|
1993
|
+
function glassLocalRect(spot) {
|
|
1994
|
+
const card = spot.querySelector("[data-composer-card]");
|
|
1995
|
+
if (card === null) {
|
|
1996
|
+
return { left: 0, top: 0, width: spot.offsetWidth, height: spot.offsetHeight };
|
|
1997
|
+
}
|
|
1998
|
+
const cardPos = localTopLeft(card, spot);
|
|
1999
|
+
let left = cardPos.x;
|
|
2000
|
+
let top = cardPos.y;
|
|
2001
|
+
let right = left + card.offsetWidth;
|
|
2002
|
+
let bottom = top + card.offsetHeight;
|
|
2003
|
+
const stats = spot.querySelector("[data-dsh-stats]");
|
|
2004
|
+
if (stats !== null) {
|
|
2005
|
+
const statsPos = localTopLeft(stats, spot);
|
|
2006
|
+
left = Math.min(left, statsPos.x);
|
|
2007
|
+
top = Math.min(top, statsPos.y);
|
|
2008
|
+
right = Math.max(right, statsPos.x + stats.offsetWidth);
|
|
2009
|
+
bottom = Math.max(bottom, statsPos.y + stats.offsetHeight);
|
|
2010
|
+
}
|
|
2011
|
+
return { left, top, width: right - left, height: bottom - top };
|
|
2012
|
+
}
|
|
2013
|
+
function ensureGlow(spot) {
|
|
2014
|
+
let glow = spot.querySelector(`:scope > [${GLOW_ATTR}]`);
|
|
2015
|
+
if (glow === null) {
|
|
2016
|
+
glow = document.createElement("div");
|
|
2017
|
+
glow.setAttribute(GLOW_ATTR, "");
|
|
2018
|
+
glow.setAttribute("aria-hidden", "true");
|
|
2019
|
+
spot.appendChild(glow);
|
|
2020
|
+
}
|
|
2021
|
+
return glow;
|
|
2022
|
+
}
|
|
2023
|
+
function startOverlayKeeper(onChange) {
|
|
2024
|
+
const tick = () => {
|
|
2025
|
+
for (const spot of spotElements()) ensureGlow(spot);
|
|
2026
|
+
onChange();
|
|
2027
|
+
};
|
|
2028
|
+
tick();
|
|
2029
|
+
const observer = new MutationObserver(tick);
|
|
2030
|
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
2031
|
+
window.addEventListener("resize", tick, { passive: true });
|
|
2032
|
+
return () => {
|
|
2033
|
+
observer.disconnect();
|
|
2034
|
+
window.removeEventListener("resize", tick);
|
|
2035
|
+
for (const glow of document.querySelectorAll(`[${GLOW_ATTR}]`)) glow.remove();
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// src/client/spotlight.ts
|
|
2040
|
+
var SPOTLIGHT_ATTRIBUTE = "data-dsh-aqua-spotlight";
|
|
2041
|
+
var PRESS_ATTRIBUTE = "data-dsh-aqua-press";
|
|
2042
|
+
var GLOW_RADIUS = 180;
|
|
2043
|
+
var GLOW_FALLBACK = "rgba(90, 215, 255, 0.17)";
|
|
2044
|
+
var TILT_MAX = 0.0175;
|
|
2045
|
+
var TILT_PERSPECTIVE = 800;
|
|
2046
|
+
var SETTLE_MS = 240;
|
|
2047
|
+
function glowGated() {
|
|
2048
|
+
return document.documentElement.hasAttribute(SPOTLIGHT_ATTRIBUTE);
|
|
2049
|
+
}
|
|
2050
|
+
function tiltGated() {
|
|
2051
|
+
return document.documentElement.hasAttribute(PRESS_ATTRIBUTE);
|
|
2052
|
+
}
|
|
2053
|
+
function hoverGated() {
|
|
2054
|
+
return glowGated() || tiltGated();
|
|
2055
|
+
}
|
|
2056
|
+
function tiltable(spot) {
|
|
2057
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return false;
|
|
2058
|
+
if (spot.matches("header[data-window-drag]")) return false;
|
|
2059
|
+
if (spot.matches('[class*="sidebarCol"]') && document.querySelector('[role="dialog"]') !== null) return false;
|
|
2060
|
+
return true;
|
|
2061
|
+
}
|
|
2062
|
+
function startSpotlight() {
|
|
2063
|
+
let current = null;
|
|
2064
|
+
let session = null;
|
|
2065
|
+
let raf = 0;
|
|
2066
|
+
let refreshRaf = 0;
|
|
2067
|
+
const tilted = /* @__PURE__ */ new WeakSet();
|
|
2068
|
+
const settle = /* @__PURE__ */ new Map();
|
|
2069
|
+
const easeBack = (spot) => {
|
|
2070
|
+
if (!tilted.has(spot)) return;
|
|
2071
|
+
tilted.delete(spot);
|
|
2072
|
+
spot.style.transform = `perspective(${TILT_PERSPECTIVE}px) rotateX(0rad) rotateY(0rad) scale(1)`;
|
|
2073
|
+
const id5 = window.setTimeout(() => {
|
|
2074
|
+
settle.delete(spot);
|
|
2075
|
+
spot.style.removeProperty("transform");
|
|
2076
|
+
spot.style.removeProperty("transform-origin");
|
|
2077
|
+
}, SETTLE_MS);
|
|
2078
|
+
settle.set(spot, id5);
|
|
2079
|
+
};
|
|
2080
|
+
const clearSpot = (spot) => {
|
|
2081
|
+
spot.removeAttribute(ON_ATTR);
|
|
2082
|
+
if (current === spot) {
|
|
2083
|
+
current = null;
|
|
2084
|
+
session = null;
|
|
2085
|
+
}
|
|
2086
|
+
const glow = spot.querySelector(`:scope > [${GLOW_ATTR}]`);
|
|
2087
|
+
if (glow !== null) glow.style.removeProperty("background-image");
|
|
2088
|
+
easeBack(spot);
|
|
2089
|
+
};
|
|
2090
|
+
const measure = (spot) => {
|
|
2091
|
+
const visual = visualRect(spot);
|
|
2092
|
+
const local = glassLocalRect(spot);
|
|
2093
|
+
const glow = glowGated() ? ensureGlow(spot) : null;
|
|
2094
|
+
if (glow !== null) {
|
|
2095
|
+
glow.style.left = `${local.left}px`;
|
|
2096
|
+
glow.style.top = `${local.top}px`;
|
|
2097
|
+
glow.style.width = `${local.width}px`;
|
|
2098
|
+
glow.style.height = `${local.height}px`;
|
|
2099
|
+
}
|
|
2100
|
+
return { spot, visual, local, glow };
|
|
2101
|
+
};
|
|
2102
|
+
const paint = (s, clientX, clientY) => {
|
|
2103
|
+
if (raf !== 0) return;
|
|
2104
|
+
raf = requestAnimationFrame(() => {
|
|
2105
|
+
raf = 0;
|
|
2106
|
+
const { spot, visual, local } = s;
|
|
2107
|
+
if (!inside(visual, clientX, clientY)) {
|
|
2108
|
+
clearSpot(spot);
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
let glow = s.glow;
|
|
2112
|
+
if (glow === null && glowGated()) {
|
|
2113
|
+
s = session = measure(spot);
|
|
2114
|
+
glow = s.glow;
|
|
2115
|
+
}
|
|
2116
|
+
if (glow !== null) {
|
|
2117
|
+
if (glowGated()) {
|
|
2118
|
+
glow.style.backgroundImage = `radial-gradient(${GLOW_RADIUS}px at ${clientX - visual.left}px ${clientY - visual.top}px, var(--dsh-aqua-spot-color, ${GLOW_FALLBACK}), transparent 70%)`;
|
|
2119
|
+
} else {
|
|
2120
|
+
glow.style.removeProperty("background-image");
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
if (tiltGated() && tiltable(spot)) {
|
|
2124
|
+
const dx = Math.min(0.5, Math.max(-0.5, (clientX - visual.left) / visual.width - 0.5));
|
|
2125
|
+
const dy = Math.min(0.5, Math.max(-0.5, (clientY - visual.top) / visual.height - 0.5));
|
|
2126
|
+
const tiltMax = spot.hasAttribute("data-dsh-trajectory") ? TILT_MAX * 0.5 : TILT_MAX;
|
|
2127
|
+
spot.style.transformOrigin = `${local.left + local.width / 2}px ${local.top + local.height / 2}px`;
|
|
2128
|
+
spot.style.transform = `perspective(${TILT_PERSPECTIVE}px) rotateX(${tiltMax * -2 * dy}rad) rotateY(${tiltMax * 2 * dx}rad) scale(1.01)`;
|
|
2129
|
+
tilted.add(spot);
|
|
2130
|
+
} else if (tilted.has(spot)) {
|
|
2131
|
+
easeBack(spot);
|
|
2132
|
+
}
|
|
2133
|
+
});
|
|
2134
|
+
};
|
|
2135
|
+
const onMove = (event) => {
|
|
2136
|
+
if (!hoverGated()) return;
|
|
2137
|
+
const spot = closestSpot(event.target);
|
|
2138
|
+
if (spot === null || session?.spot !== spot) return;
|
|
2139
|
+
paint(session, event.clientX, event.clientY);
|
|
2140
|
+
};
|
|
2141
|
+
const onOver = (event) => {
|
|
2142
|
+
if (!hoverGated()) return;
|
|
2143
|
+
const spot = closestSpot(event.target);
|
|
2144
|
+
if (spot === null) return;
|
|
2145
|
+
if (spot.matches('[class*="sidebarCol"]') && document.querySelector('[role="dialog"]') !== null) return;
|
|
2146
|
+
const next = measure(spot);
|
|
2147
|
+
if (!inside(next.visual, event.clientX, event.clientY)) return;
|
|
2148
|
+
const id5 = settle.get(spot);
|
|
2149
|
+
if (id5 !== void 0) {
|
|
2150
|
+
clearTimeout(id5);
|
|
2151
|
+
settle.delete(spot);
|
|
2152
|
+
}
|
|
2153
|
+
spot.setAttribute(ON_ATTR, "");
|
|
2154
|
+
current = spot;
|
|
2155
|
+
session = next;
|
|
2156
|
+
paint(next, event.clientX, event.clientY);
|
|
2157
|
+
};
|
|
2158
|
+
const onOut = (event) => {
|
|
2159
|
+
const spot = closestSpot(event.target);
|
|
2160
|
+
if (spot === null || spot !== current) return;
|
|
2161
|
+
if (session !== null && inside(session.visual, event.clientX, event.clientY)) return;
|
|
2162
|
+
clearSpot(spot);
|
|
2163
|
+
};
|
|
2164
|
+
const keeper = startOverlayKeeper(() => {
|
|
2165
|
+
for (const spot of spotElements()) {
|
|
2166
|
+
if (!spot.matches('[class*="sidebarCol"]')) continue;
|
|
2167
|
+
if (spot.querySelector('[role="dialog"]') === null) continue;
|
|
2168
|
+
spot.removeAttribute(ON_ATTR);
|
|
2169
|
+
const id5 = settle.get(spot);
|
|
2170
|
+
if (id5 !== void 0) {
|
|
2171
|
+
clearTimeout(id5);
|
|
2172
|
+
settle.delete(spot);
|
|
2173
|
+
}
|
|
2174
|
+
tilted.delete(spot);
|
|
2175
|
+
spot.style.setProperty("transition", "none");
|
|
2176
|
+
spot.style.removeProperty("transform");
|
|
2177
|
+
spot.style.removeProperty("transform-origin");
|
|
2178
|
+
void spot.offsetWidth;
|
|
2179
|
+
spot.style.removeProperty("transition");
|
|
2180
|
+
if (current === spot) {
|
|
2181
|
+
current = null;
|
|
2182
|
+
session = null;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
if (session === null || refreshRaf !== 0) return;
|
|
2186
|
+
refreshRaf = requestAnimationFrame(() => {
|
|
2187
|
+
refreshRaf = 0;
|
|
2188
|
+
if (session !== null) session = measure(session.spot);
|
|
2189
|
+
});
|
|
2190
|
+
});
|
|
2191
|
+
document.addEventListener("pointermove", onMove, { passive: true });
|
|
2192
|
+
document.addEventListener("pointerover", onOver, { passive: true });
|
|
2193
|
+
document.addEventListener("pointerout", onOut, { passive: true });
|
|
2194
|
+
return () => {
|
|
2195
|
+
document.removeEventListener("pointermove", onMove);
|
|
2196
|
+
document.removeEventListener("pointerover", onOver);
|
|
2197
|
+
document.removeEventListener("pointerout", onOut);
|
|
2198
|
+
keeper();
|
|
2199
|
+
if (raf !== 0) cancelAnimationFrame(raf);
|
|
2200
|
+
if (refreshRaf !== 0) cancelAnimationFrame(refreshRaf);
|
|
2201
|
+
for (const id5 of settle.values()) clearTimeout(id5);
|
|
2202
|
+
settle.clear();
|
|
2203
|
+
for (const spot of spotElements()) {
|
|
2204
|
+
spot.removeAttribute(ON_ATTR);
|
|
2205
|
+
if (tilted.has(spot)) {
|
|
2206
|
+
tilted.delete(spot);
|
|
2207
|
+
spot.style.removeProperty("transform");
|
|
2208
|
+
spot.style.removeProperty("transform-origin");
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
};
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
// src/client/theme-layer.ts
|
|
2215
|
+
var AQUA_ATTRIBUTE = "data-dsh-aqua";
|
|
2216
|
+
var AQUA_ENABLED_KEY = "dsh.ui-aqua.enabled";
|
|
2217
|
+
var DEFAULT_ENABLED = true;
|
|
2218
|
+
var OVERRIDE_SOURCE = "dsh-transparent-ui";
|
|
2219
|
+
var FONT_STACK = "'Space Grotesk Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif";
|
|
2220
|
+
var both = (value) => ({ light: value, dark: value });
|
|
2221
|
+
var AQUA_TOKEN_OVERRIDES = {
|
|
2222
|
+
// Typography: Space Grotesk for Latin/digits, CJK keeps the system stack.
|
|
2223
|
+
"--dsw-font-family": both(FONT_STACK),
|
|
2224
|
+
// Backgrounds.
|
|
2225
|
+
"--dsw-alias-bg-base": { light: "#F4F8FD", dark: "#0C121B" },
|
|
2226
|
+
"--dsw-alias-bg-layer-1": { light: "#FFFFFF", dark: "#111A27" },
|
|
2227
|
+
"--dsw-alias-bg-layer-2": { light: "#ECF2FA", dark: "#162130" },
|
|
2228
|
+
"--dsw-alias-bg-layer-3": { light: "#E2EBF7", dark: "#1C2A3D" },
|
|
2229
|
+
"--dsw-alias-bg-overlay": { light: "#DCE7F4", dark: "#22334A" },
|
|
2230
|
+
"--dsw-alias-bg-module-platform": { light: "#FFFFFF", dark: "#111A27" },
|
|
2231
|
+
"--dsw-alias-bg-multi-select": { light: "#FFFFFF", dark: "#162130" },
|
|
2232
|
+
"--dsw-alias-bg-skeleton": { light: "rgba(19, 45, 83, 0.08)", dark: "rgba(148, 180, 220, 0.12)" },
|
|
2233
|
+
"--dsw-alias-bg-mask-1": { light: "rgba(19, 37, 62, 0.3)", dark: "rgba(4, 8, 14, 0.55)" },
|
|
2234
|
+
"--dsw-alias-bg-mask-2": { light: "rgba(19, 37, 62, 0.12)", dark: "rgba(4, 8, 14, 0.25)" },
|
|
2235
|
+
"--dsw-alias-bg-mask-3": { light: "rgba(19, 37, 62, 0.3)", dark: "rgba(4, 8, 14, 0.5)" },
|
|
2236
|
+
"--dsw-alias-bg-mask-drop": { light: "rgba(244, 248, 253, 0.72)", dark: "rgba(12, 18, 27, 0.7)" },
|
|
2237
|
+
// Hairlines and strokes.
|
|
2238
|
+
"--dsw-alias-border-l1": { light: "rgba(19, 45, 83, 0.08)", dark: "rgba(148, 180, 220, 0.08)" },
|
|
2239
|
+
"--dsw-alias-border-l2": { light: "rgba(19, 45, 83, 0.14)", dark: "rgba(148, 180, 220, 0.15)" },
|
|
2240
|
+
"--dsw-alias-border-l2-darkmode-thin": { light: "rgba(19, 45, 83, 0.1)", dark: "rgba(148, 180, 220, 0.1)" },
|
|
2241
|
+
"--dsw-alias-border-l3": { light: "rgba(19, 45, 83, 0.22)", dark: "rgba(148, 180, 220, 0.24)" },
|
|
2242
|
+
"--dsw-alias-border-l4": { light: "rgba(19, 45, 83, 0.32)", dark: "rgba(148, 180, 220, 0.34)" },
|
|
2243
|
+
"--dsw-alias-border-inverted": { light: "rgba(19, 45, 83, 0.06)", dark: "rgba(148, 180, 220, 0.12)" },
|
|
2244
|
+
"--dsw-alias-border-inverted2": { light: "rgba(19, 45, 83, 0.08)", dark: "rgba(148, 180, 220, 0.08)" },
|
|
2245
|
+
// Text ink.
|
|
2246
|
+
"--dsw-alias-label-primary": { light: "#13243E", dark: "#EAF2FC" },
|
|
2247
|
+
"--dsw-alias-label-secondary": { light: "#40597A", dark: "#AFC3DC" },
|
|
2248
|
+
"--dsw-alias-label-tertiary": { light: "#5D7696", dark: "#8399B5" },
|
|
2249
|
+
"--dsw-alias-label-caption": { light: "#7E93AC", dark: "#6B829F" },
|
|
2250
|
+
"--dsw-alias-label-dimmed": { light: "#C9D4E2", dark: "#4E5F76" },
|
|
2251
|
+
"--dsw-alias-label-primary-bluish": { light: "#2E5EB8", dark: "#BFD6F6" },
|
|
2252
|
+
"--dsw-alias-label-primary-dimmed": { light: "#1E3556", dark: "#D7E3F4" },
|
|
2253
|
+
"--dsw-alias-label-primary-inverted": { light: "#FFFFFF", dark: "#162130" },
|
|
2254
|
+
"--dsw-alias-label-primary-foreground": { light: "#FFFFFF", dark: "#FFFFFF" },
|
|
2255
|
+
// Brand (wordmark ink stays scheme ink; accents go business blue).
|
|
2256
|
+
"--dsw-alias-brand-primary": { light: "#13243E", dark: "#EAF2FC" },
|
|
2257
|
+
"--dsw-alias-brand-text": { light: "#13243E", dark: "#EAF2FC" },
|
|
2258
|
+
"--dsw-alias-brand-primary-invert": { light: "#FFFFFF", dark: "#0C121B" },
|
|
2259
|
+
"--dsw-alias-brand-primary-new-colorprimary-new-color": { light: "#3F76D8", dark: "#6E9BE8" },
|
|
2260
|
+
// States.
|
|
2261
|
+
"--dsw-alias-state-business-primary": { light: "#3F76D8", dark: "#6E9BE8" },
|
|
2262
|
+
"--dsw-alias-state-business-tertiary": { light: "#DCE9FB", dark: "#1D2C44" },
|
|
2263
|
+
"--dsw-alias-state-success-tertiary": { light: "#DDF3E4", dark: "#12271C" },
|
|
2264
|
+
"--dsw-alias-state-warn-tertiary": { light: "#FCEED6", dark: "#2A2416" },
|
|
2265
|
+
// Buttons: the primary action becomes business blue with white ink.
|
|
2266
|
+
"--dsw-alias-button-primary-fill": { light: "#3F76D8", dark: "#4A7FD9" },
|
|
2267
|
+
"--dsw-alias-button-primary-hover": { light: "#5C8DE0", dark: "#5E8FE6" },
|
|
2268
|
+
"--dsw-alias-button-primary-dimmed": { light: "#DCE9FB", dark: "#162130" },
|
|
2269
|
+
"--dsw-alias-button-info-fill": { light: "#3F76D8", dark: "#6E9BE8" },
|
|
2270
|
+
"--dsw-alias-button-info-hover": { light: "#5C8DE0", dark: "#7FA8EF" },
|
|
2271
|
+
"--dsw-alias-button-elevated-fill": { light: "#FFFFFF", dark: "#162130" },
|
|
2272
|
+
"--dsw-alias-button-floating-fill": { light: "#FFFFFF", dark: "#162130" },
|
|
2273
|
+
"--dsw-alias-button-floating-hover": { light: "#F0F5FB", dark: "#1C2A3D" },
|
|
2274
|
+
"--dsw-alias-button-contrast-fill": { light: "#26364D", dark: "#EAF2FC" },
|
|
2275
|
+
"--dsw-alias-button-ghost-active-fill": { light: "#DCE7F4", dark: "#1C2A3D" },
|
|
2276
|
+
"--dsw-alias-button-ghost-active-hover": { light: "#E9F0F8", dark: "#162130" },
|
|
2277
|
+
"--dsw-alias-button-ghost-active-border": { light: "#8FA3BC", dark: "#6B829F" },
|
|
2278
|
+
// Interaction fills.
|
|
2279
|
+
"--dsw-alias-interactive-bg-hover": { light: "rgba(63, 118, 216, 0.08)", dark: "rgba(126, 164, 223, 0.1)" },
|
|
2280
|
+
"--dsw-alias-interactive-bg-hover-accent": { light: "rgba(63, 118, 216, 0.14)", dark: "rgba(126, 164, 223, 0.2)" },
|
|
2281
|
+
"--dsw-alias-interactive-bg-active": { light: "rgba(63, 118, 216, 0.2)", dark: "rgba(126, 164, 223, 0.26)" },
|
|
2282
|
+
"--dsw-alias-interactive-bg-hover-danger": { light: "rgba(236, 19, 19, 0.05)", dark: "rgba(242, 90, 90, 0.14)" },
|
|
2283
|
+
"--dsw-alias-interactive-bg-hover-solid": { light: "#F0F5FB", dark: "#1C2A3D" },
|
|
2284
|
+
// Markdown / code surfaces.
|
|
2285
|
+
"--dsw-alias-markdown-code-block": { light: "#F0F5FB", dark: "#0D141F" },
|
|
2286
|
+
"--dsw-alias-markdown-code-block-banner": { light: "#F5F8FD", dark: "#121B29" },
|
|
2287
|
+
"--dsw-alias-markdown-inline-code": { light: "#E4EDF8", dark: "#172334" },
|
|
2288
|
+
"--dsw-alias-markdown-citation": { light: "#EAF1F9", dark: "#1A2534" },
|
|
2289
|
+
"--dsw-alias-markdown-tag": { light: "#E4EDF8", dark: "#162130" },
|
|
2290
|
+
"--dsw-alias-markdown-placeholder": { light: "#EAF1F9", dark: "#131D2B" },
|
|
2291
|
+
"--dsw-alias-markdown-code-segment-selected": { light: "#FFFFFF", dark: "#1C2A3D" },
|
|
2292
|
+
"--dsw-alias-markdown-code-segment-unselected": { light: "#F0F5FB", dark: "#0F1723" },
|
|
2293
|
+
// Scrollbars.
|
|
2294
|
+
"--dsw-alias-scrollbar-bg-l1": { light: "rgba(63, 118, 216, 0.28)", dark: "rgba(126, 164, 223, 0.28)" },
|
|
2295
|
+
"--dsw-alias-scrollbar-bg-l2": { light: "rgba(63, 118, 216, 0.4)", dark: "rgba(126, 164, 223, 0.36)" },
|
|
2296
|
+
"--dsw-alias-scrollbar-hover-l1": { light: "rgba(63, 118, 216, 0.5)", dark: "rgba(126, 164, 223, 0.44)" },
|
|
2297
|
+
"--dsw-alias-scrollbar-hover-l2": { light: "rgba(63, 118, 216, 0.6)", dark: "rgba(126, 164, 223, 0.52)" },
|
|
2298
|
+
// Specific surfaces. The sidebar root fill goes transparent — the glass
|
|
2299
|
+
// panel styling lives on the column itself, so no double tint.
|
|
2300
|
+
"--dsw-specific-sidebar-fill": { light: "transparent", dark: "transparent" },
|
|
2301
|
+
"--dsw-specific-sidebar-nav-item-active": { light: "#DEE9F8", dark: "#1B283A" },
|
|
2302
|
+
"--dsw-specific-sidebar-nav-item-hover": { light: "#E9F0F8", dark: "#15202F" },
|
|
2303
|
+
"--dsw-specific-sidebar-nav-item-active-accent": { light: "#3F76D8", dark: "#6E9BE8" },
|
|
2304
|
+
"--dsw-specific-input-major": { light: "#FFFFFF", dark: "#101927" },
|
|
2305
|
+
"--dsw-specific-login-input": { light: "#F0F5FB", dark: "#0D141F" },
|
|
2306
|
+
"--dsw-specific-menu": { light: "#EAF1F9", dark: "#162130" },
|
|
2307
|
+
"--dsw-specific-selector": { light: "#EAF1F9", dark: "#1C2A3D" },
|
|
2308
|
+
"--dsw-specific-bubble": { light: "#F0F5FC", dark: "#121C2A" },
|
|
2309
|
+
"--dsw-specific-bubble-highlight": { light: "#DCE9FB", dark: "#1A283A" },
|
|
2310
|
+
"--dsw-specific-tip": { light: "#EAF1F9", dark: "#131D2B" },
|
|
2311
|
+
"--dsw-alias-toast-bg": { light: "#1B3256", dark: "#1C2A3D" },
|
|
2312
|
+
"--dsw-alias-tooltip-bg": { light: "#13243E", dark: "#162130" },
|
|
2313
|
+
// Elevation shadows (blue-tinted depth).
|
|
2314
|
+
"--dsw-shadow-lv1": { light: "0 2px 4px rgba(19, 45, 83, 0.06)", dark: "0 2px 4px rgba(2, 6, 14, 0.5)" },
|
|
2315
|
+
"--dsw-shadow-lv1-blur": { light: "0 4px 12px rgba(19, 45, 83, 0.05)", dark: "0 4px 12px rgba(2, 6, 14, 0.4)" },
|
|
2316
|
+
"--dsw-shadow-lv2": {
|
|
2317
|
+
light: "0 4px 12px rgba(19, 45, 83, 0.05), 0 2px 8px rgba(19, 45, 83, 0.06)",
|
|
2318
|
+
dark: "0 4px 12px rgba(2, 6, 14, 0.4), 0 2px 8px rgba(2, 6, 14, 0.35)"
|
|
2319
|
+
},
|
|
2320
|
+
"--dsw-shadow-lv3": {
|
|
2321
|
+
light: "0 0 1px rgba(19, 45, 83, 0.08), 0 12px 32px rgba(19, 45, 83, 0.12)",
|
|
2322
|
+
dark: "0 0 1px rgba(2, 6, 14, 0.6), 0 12px 32px rgba(2, 6, 14, 0.55)"
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
var COMPAT_SURFACE_OVERRIDES = {
|
|
2326
|
+
"--dsw-alias-bg-layer-1": { light: "rgba(255, 255, 255, 0.55)", dark: "rgba(17, 26, 39, 0.55)" },
|
|
2327
|
+
"--dsw-alias-bg-layer-2": { light: "rgba(236, 242, 250, 0.5)", dark: "rgba(22, 33, 48, 0.55)" },
|
|
2328
|
+
"--dsw-alias-bg-layer-3": { light: "rgba(226, 235, 247, 0.45)", dark: "rgba(28, 42, 61, 0.5)" },
|
|
2329
|
+
"--dsw-alias-bg-overlay": { light: "rgba(220, 231, 244, 0.6)", dark: "rgba(34, 51, 74, 0.6)" },
|
|
2330
|
+
"--dsw-alias-bg-module-platform": { light: "rgba(255, 255, 255, 0.55)", dark: "rgba(17, 26, 39, 0.55)" },
|
|
2331
|
+
"--dsw-alias-bg-multi-select": { light: "rgba(255, 255, 255, 0.55)", dark: "rgba(22, 33, 48, 0.55)" },
|
|
2332
|
+
"--dsw-specific-menu": { light: "rgba(234, 241, 249, 0.6)", dark: "rgba(22, 33, 48, 0.6)" },
|
|
2333
|
+
"--dsw-specific-selector": { light: "rgba(234, 241, 249, 0.55)", dark: "rgba(28, 42, 61, 0.55)" },
|
|
2334
|
+
"--dsw-specific-bubble": { light: "rgba(240, 245, 252, 0.55)", dark: "rgba(18, 28, 42, 0.55)" },
|
|
2335
|
+
"--dsw-specific-bubble-highlight": { light: "rgba(220, 233, 251, 0.55)", dark: "rgba(26, 40, 58, 0.55)" },
|
|
2336
|
+
"--dsw-specific-tip": { light: "rgba(234, 241, 249, 0.6)", dark: "rgba(19, 29, 43, 0.6)" },
|
|
2337
|
+
"--dsw-specific-input-major": { light: "rgba(255, 255, 255, 0.5)", dark: "rgba(16, 25, 39, 0.5)" },
|
|
2338
|
+
"--dsw-specific-login-input": { light: "rgba(240, 245, 251, 0.5)", dark: "rgba(13, 20, 31, 0.5)" },
|
|
2339
|
+
"--dsw-alias-markdown-code-block": { light: "rgba(240, 245, 251, 0.5)", dark: "rgba(13, 20, 31, 0.5)" },
|
|
2340
|
+
"--dsw-alias-markdown-code-block-banner": { light: "rgba(245, 248, 253, 0.55)", dark: "rgba(18, 27, 41, 0.55)" },
|
|
2341
|
+
"--dsw-alias-markdown-inline-code": { light: "rgba(228, 237, 248, 0.5)", dark: "rgba(23, 35, 52, 0.5)" },
|
|
2342
|
+
"--dsw-alias-markdown-citation": { light: "rgba(234, 241, 249, 0.55)", dark: "rgba(26, 37, 52, 0.55)" },
|
|
2343
|
+
"--dsw-alias-markdown-tag": { light: "rgba(228, 237, 248, 0.5)", dark: "rgba(22, 33, 48, 0.5)" },
|
|
2344
|
+
"--dsw-alias-markdown-placeholder": { light: "rgba(234, 241, 249, 0.55)", dark: "rgba(19, 29, 43, 0.55)" },
|
|
2345
|
+
"--dsw-alias-toast-bg": { light: "rgba(27, 50, 86, 0.85)", dark: "rgba(28, 42, 61, 0.85)" },
|
|
2346
|
+
"--dsw-alias-tooltip-bg": { light: "rgba(19, 36, 62, 0.88)", dark: "rgba(22, 33, 48, 0.88)" }
|
|
2347
|
+
};
|
|
2348
|
+
var COMPAT_TOKEN_OVERRIDES = { ...AQUA_TOKEN_OVERRIDES, ...COMPAT_SURFACE_OVERRIDES };
|
|
2349
|
+
function readEnabled() {
|
|
2350
|
+
try {
|
|
2351
|
+
const raw = localStorage.getItem(AQUA_ENABLED_KEY);
|
|
2352
|
+
return raw === null ? DEFAULT_ENABLED : raw === "true";
|
|
2353
|
+
} catch {
|
|
2354
|
+
return DEFAULT_ENABLED;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
function writeEnabled(value) {
|
|
2358
|
+
try {
|
|
2359
|
+
localStorage.setItem(AQUA_ENABLED_KEY, String(value));
|
|
2360
|
+
} catch {
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
var SETTINGS_DEFAULTS = {
|
|
2364
|
+
mode: "mica",
|
|
2365
|
+
blur: 20,
|
|
2366
|
+
frost: 7,
|
|
2367
|
+
bgBrightness: 50,
|
|
2368
|
+
background: "fluid",
|
|
2369
|
+
wallpaper: "",
|
|
2370
|
+
whale: true,
|
|
2371
|
+
critters: true,
|
|
2372
|
+
mesh: true,
|
|
2373
|
+
spotlight: true,
|
|
2374
|
+
press: true,
|
|
2375
|
+
fluidHue: 320,
|
|
2376
|
+
fluidDepth: 25,
|
|
2377
|
+
wallpaperBlur: 0,
|
|
2378
|
+
wallpaperFrost: 0,
|
|
2379
|
+
videoBlur: 6,
|
|
2380
|
+
videoBrightness: 45
|
|
2381
|
+
};
|
|
2382
|
+
var NUMERIC_KEYS = {
|
|
2383
|
+
blur: "dsh.ui-aqua.blur",
|
|
2384
|
+
frost: "dsh.ui-aqua.frost",
|
|
2385
|
+
fluidHue: "dsh.ui-aqua.fluidHue",
|
|
2386
|
+
fluidDepth: "dsh.ui-aqua.fluidDepth",
|
|
2387
|
+
bgBrightness: "dsh.ui-aqua.bgBrightness",
|
|
2388
|
+
wallpaperBlur: "dsh.ui-aqua.wallpaperBlur",
|
|
2389
|
+
wallpaperFrost: "dsh.ui-aqua.wallpaperFrost",
|
|
2390
|
+
videoBlur: "dsh.ui-aqua.videoBlur",
|
|
2391
|
+
videoBrightness: "dsh.ui-aqua.videoBrightness"
|
|
2392
|
+
};
|
|
2393
|
+
var MODE_KEY = "dsh.ui-aqua.mode";
|
|
2394
|
+
var BACKGROUND_KEY = "dsh.ui-aqua.background";
|
|
2395
|
+
var WALLPAPER_KEY = "dsh.ui-aqua.wallpaper";
|
|
2396
|
+
var WHALE_KEY = "dsh.ui-aqua.whale";
|
|
2397
|
+
var CRITTERS_KEY = "dsh.ui-aqua.critters";
|
|
2398
|
+
var MESH_KEY = "dsh.ui-aqua.mesh";
|
|
2399
|
+
var SPOTLIGHT_KEY = "dsh.ui-aqua.spotlight";
|
|
2400
|
+
var PRESS_KEY = "dsh.ui-aqua.press";
|
|
2401
|
+
function clampSetting(key, value) {
|
|
2402
|
+
const max = key === "blur" || key === "wallpaperBlur" || key === "videoBlur" ? 40 : key === "frost" || key === "wallpaperFrost" || key === "bgBrightness" || key === "videoBrightness" ? 100 : 360;
|
|
2403
|
+
return Number.isFinite(value) ? Math.min(max, Math.max(0, value)) : SETTINGS_DEFAULTS[key];
|
|
2404
|
+
}
|
|
2405
|
+
function readSetting(key) {
|
|
2406
|
+
try {
|
|
2407
|
+
const raw = localStorage.getItem(NUMERIC_KEYS[key]);
|
|
2408
|
+
return raw === null ? SETTINGS_DEFAULTS[key] : clampSetting(key, Number(raw));
|
|
2409
|
+
} catch {
|
|
2410
|
+
return SETTINGS_DEFAULTS[key];
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
function writeSetting(key, value) {
|
|
2414
|
+
try {
|
|
2415
|
+
localStorage.setItem(NUMERIC_KEYS[key], String(value));
|
|
2416
|
+
} catch {
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
function readBackground() {
|
|
2420
|
+
try {
|
|
2421
|
+
return localStorage.getItem(BACKGROUND_KEY) === "wallpaper" ? "wallpaper" : "fluid";
|
|
2422
|
+
} catch {
|
|
2423
|
+
return "fluid";
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
function writeBackground(value) {
|
|
2427
|
+
try {
|
|
2428
|
+
localStorage.setItem(BACKGROUND_KEY, value);
|
|
2429
|
+
} catch {
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
function readMode() {
|
|
2433
|
+
try {
|
|
2434
|
+
const stored = localStorage.getItem(MODE_KEY);
|
|
2435
|
+
if (stored === "compat") return "compat";
|
|
2436
|
+
return "mica";
|
|
2437
|
+
} catch {
|
|
2438
|
+
return "mica";
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
function writeMode(value) {
|
|
2442
|
+
try {
|
|
2443
|
+
localStorage.setItem(MODE_KEY, value);
|
|
2444
|
+
} catch {
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
function readWallpaper() {
|
|
2448
|
+
try {
|
|
2449
|
+
return localStorage.getItem(WALLPAPER_KEY) ?? "";
|
|
2450
|
+
} catch {
|
|
2451
|
+
return "";
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
function writeWallpaper(value) {
|
|
2455
|
+
try {
|
|
2456
|
+
localStorage.setItem(WALLPAPER_KEY, value);
|
|
2457
|
+
} catch {
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
function readWhale() {
|
|
2461
|
+
try {
|
|
2462
|
+
const raw = localStorage.getItem(WHALE_KEY);
|
|
2463
|
+
return raw === null ? true : raw === "true";
|
|
2464
|
+
} catch {
|
|
2465
|
+
return true;
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
function writeWhale(value) {
|
|
2469
|
+
try {
|
|
2470
|
+
localStorage.setItem(WHALE_KEY, String(value));
|
|
2471
|
+
} catch {
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
function readCritters() {
|
|
2475
|
+
try {
|
|
2476
|
+
const raw = localStorage.getItem(CRITTERS_KEY);
|
|
2477
|
+
return raw === null ? true : raw === "true";
|
|
2478
|
+
} catch {
|
|
2479
|
+
return true;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
function writeCritters(value) {
|
|
2483
|
+
try {
|
|
2484
|
+
localStorage.setItem(CRITTERS_KEY, String(value));
|
|
2485
|
+
} catch {
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
function readMesh() {
|
|
2489
|
+
try {
|
|
2490
|
+
const raw = localStorage.getItem(MESH_KEY);
|
|
2491
|
+
return raw === null ? true : raw === "true";
|
|
2492
|
+
} catch {
|
|
2493
|
+
return true;
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
function writeMesh(value) {
|
|
2497
|
+
try {
|
|
2498
|
+
localStorage.setItem(MESH_KEY, String(value));
|
|
2499
|
+
} catch {
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
function readSpotlight() {
|
|
2503
|
+
try {
|
|
2504
|
+
const raw = localStorage.getItem(SPOTLIGHT_KEY);
|
|
2505
|
+
return raw === null ? true : raw === "true";
|
|
2506
|
+
} catch {
|
|
2507
|
+
return true;
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
function writeSpotlight(value) {
|
|
2511
|
+
try {
|
|
2512
|
+
localStorage.setItem(SPOTLIGHT_KEY, String(value));
|
|
2513
|
+
} catch {
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
function readPress() {
|
|
2517
|
+
try {
|
|
2518
|
+
localStorage.removeItem("dsh.ui-aqua.entrance");
|
|
2519
|
+
const raw = localStorage.getItem(PRESS_KEY);
|
|
2520
|
+
return raw === null ? true : raw === "true";
|
|
2521
|
+
} catch {
|
|
2522
|
+
return true;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
function writePress(value) {
|
|
2526
|
+
try {
|
|
2527
|
+
localStorage.setItem(PRESS_KEY, String(value));
|
|
2528
|
+
} catch {
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
function activeScheme() {
|
|
2532
|
+
return document.body.hasAttribute("data-ds-dark-theme") ? "dark" : "light";
|
|
2533
|
+
}
|
|
2534
|
+
var AquaLayer = class {
|
|
2535
|
+
enabled = false;
|
|
2536
|
+
settings = { ...SETTINGS_DEFAULTS };
|
|
2537
|
+
/** Resolved palette scheme: dark = the brightness knob darkens, light = it brightens. */
|
|
2538
|
+
dark = false;
|
|
2539
|
+
tokenDisposer;
|
|
2540
|
+
mainFluid;
|
|
2541
|
+
interactionDisposer;
|
|
2542
|
+
themeListener;
|
|
2543
|
+
seamDisposer;
|
|
2544
|
+
spotlightDisposer;
|
|
2545
|
+
whaleHandle;
|
|
2546
|
+
meshHandle;
|
|
2547
|
+
/** Object URL of the current large-video wallpaper (revoked on replace). */
|
|
2548
|
+
videoObjectUrl;
|
|
2549
|
+
/** IndexedDB id backing the current object URL (guards against reloads). */
|
|
2550
|
+
videoBlobId;
|
|
2551
|
+
ctx;
|
|
2552
|
+
/**
|
|
2553
|
+
* @param ctx - owning client context.
|
|
2554
|
+
*/
|
|
2555
|
+
constructor(ctx) {
|
|
2556
|
+
this.ctx = ctx;
|
|
2557
|
+
ctx.effect(() => {
|
|
2558
|
+
const onStorage = (event) => {
|
|
2559
|
+
if (event.key === AQUA_ENABLED_KEY) {
|
|
2560
|
+
this.enabled = readEnabled();
|
|
2561
|
+
this.sync();
|
|
2562
|
+
}
|
|
2563
|
+
const key = event.key;
|
|
2564
|
+
if (key !== null && (key in NUMERIC_KEYS || key === BACKGROUND_KEY || key === WALLPAPER_KEY || key === MODE_KEY || key === WHALE_KEY || key === CRITTERS_KEY || key === MESH_KEY || key === SPOTLIGHT_KEY || key === PRESS_KEY)) {
|
|
2565
|
+
this.reloadSettings();
|
|
2566
|
+
if (this.enabled) {
|
|
2567
|
+
this.applySettings();
|
|
2568
|
+
this.applyTokens();
|
|
2569
|
+
this.applyFluidPalettes();
|
|
2570
|
+
this.syncWhale();
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
};
|
|
2574
|
+
window.addEventListener("storage", onStorage);
|
|
2575
|
+
this.themeListener = this.ctx.on("theme/change", () => {
|
|
2576
|
+
this.dark = this.resolveScheme();
|
|
2577
|
+
this.whaleHandle?.setDark(this.dark);
|
|
2578
|
+
if (this.enabled) {
|
|
2579
|
+
this.applySettings();
|
|
2580
|
+
this.applyFluidPalettes();
|
|
2581
|
+
}
|
|
2582
|
+
});
|
|
2583
|
+
return () => {
|
|
2584
|
+
window.removeEventListener("storage", onStorage);
|
|
2585
|
+
this.themeListener?.();
|
|
2586
|
+
this.themeListener = void 0;
|
|
2587
|
+
this.unmount();
|
|
2588
|
+
};
|
|
2589
|
+
}, "ui-aqua: layer lifecycle");
|
|
2590
|
+
this.enabled = readEnabled();
|
|
2591
|
+
this.reloadSettings();
|
|
2592
|
+
this.dark = this.resolveScheme();
|
|
2593
|
+
this.sync();
|
|
2594
|
+
}
|
|
2595
|
+
/** Current enable state (the settings row mirrors this). */
|
|
2596
|
+
getEnabled() {
|
|
2597
|
+
return this.enabled;
|
|
2598
|
+
}
|
|
2599
|
+
/** Current knob values (the settings row mirrors these). */
|
|
2600
|
+
getSettings() {
|
|
2601
|
+
return { ...this.settings };
|
|
2602
|
+
}
|
|
2603
|
+
/** Whether the resolved palette is dark (the brightness knob darkens). */
|
|
2604
|
+
getDark() {
|
|
2605
|
+
return this.dark;
|
|
2606
|
+
}
|
|
2607
|
+
/** Resolved scheme from the theme service (falls back to the body attribute). */
|
|
2608
|
+
resolveScheme() {
|
|
2609
|
+
try {
|
|
2610
|
+
return this.ctx.theme.getTheme().active.colorScheme === "dark";
|
|
2611
|
+
} catch {
|
|
2612
|
+
return activeScheme() === "dark";
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
/** Re-read every knob from localStorage into memory. */
|
|
2616
|
+
reloadSettings() {
|
|
2617
|
+
try {
|
|
2618
|
+
localStorage.removeItem("dsh.ui-aqua.tilt");
|
|
2619
|
+
localStorage.removeItem("dsh.ui-aqua.lens");
|
|
2620
|
+
localStorage.removeItem("dsh.ui-aqua.fluidTone");
|
|
2621
|
+
} catch {
|
|
2622
|
+
}
|
|
2623
|
+
this.settings = {
|
|
2624
|
+
mode: readMode(),
|
|
2625
|
+
blur: readSetting("blur"),
|
|
2626
|
+
frost: readSetting("frost"),
|
|
2627
|
+
fluidHue: readSetting("fluidHue"),
|
|
2628
|
+
fluidDepth: readSetting("fluidDepth"),
|
|
2629
|
+
bgBrightness: readSetting("bgBrightness"),
|
|
2630
|
+
background: readBackground(),
|
|
2631
|
+
wallpaper: readWallpaper(),
|
|
2632
|
+
whale: readWhale(),
|
|
2633
|
+
critters: readCritters(),
|
|
2634
|
+
mesh: readMesh(),
|
|
2635
|
+
spotlight: readSpotlight(),
|
|
2636
|
+
press: readPress(),
|
|
2637
|
+
wallpaperBlur: readSetting("wallpaperBlur"),
|
|
2638
|
+
wallpaperFrost: readSetting("wallpaperFrost"),
|
|
2639
|
+
videoBlur: readSetting("videoBlur"),
|
|
2640
|
+
videoBrightness: readSetting("videoBrightness")
|
|
2641
|
+
};
|
|
2642
|
+
}
|
|
2643
|
+
/** Flip the layer: persist, then apply or retract every owned effect. */
|
|
2644
|
+
setEnabled(value) {
|
|
2645
|
+
if (value === this.enabled) return;
|
|
2646
|
+
this.enabled = value;
|
|
2647
|
+
writeEnabled(value);
|
|
2648
|
+
this.sync();
|
|
2649
|
+
}
|
|
2650
|
+
/** Set the rendering mode ('mica' or 'compat'). */
|
|
2651
|
+
setMode(value) {
|
|
2652
|
+
if (value === this.settings.mode) return;
|
|
2653
|
+
this.settings.mode = value;
|
|
2654
|
+
writeMode(value);
|
|
2655
|
+
if (this.enabled) {
|
|
2656
|
+
this.applySettings();
|
|
2657
|
+
this.applyTokens();
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
/** Set the glass blur radius (px). */
|
|
2661
|
+
setBlur(value) {
|
|
2662
|
+
const next = clampSetting("blur", value);
|
|
2663
|
+
if (next === this.settings.blur) return;
|
|
2664
|
+
this.settings.blur = next;
|
|
2665
|
+
writeSetting("blur", next);
|
|
2666
|
+
if (this.enabled) this.applySettings();
|
|
2667
|
+
}
|
|
2668
|
+
/** Set the glass frost amount (0-100). */
|
|
2669
|
+
setFrost(value) {
|
|
2670
|
+
const next = clampSetting("frost", value);
|
|
2671
|
+
if (next === this.settings.frost) return;
|
|
2672
|
+
this.settings.frost = next;
|
|
2673
|
+
writeSetting("frost", next);
|
|
2674
|
+
if (this.enabled) this.applySettings();
|
|
2675
|
+
}
|
|
2676
|
+
/** Set the fluid hue (degrees, continuous). */
|
|
2677
|
+
setFluidHue(value) {
|
|
2678
|
+
const next = clampSetting("fluidHue", value);
|
|
2679
|
+
if (next === this.settings.fluidHue) return;
|
|
2680
|
+
this.settings.fluidHue = next;
|
|
2681
|
+
writeSetting("fluidHue", next);
|
|
2682
|
+
if (this.enabled) {
|
|
2683
|
+
this.applySettings();
|
|
2684
|
+
this.applyFluidPalettes();
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
/** Set the fluid depth (0-100, continuous: deep ↔ pale). */
|
|
2688
|
+
setFluidDepth(value) {
|
|
2689
|
+
const next = clampSetting("fluidDepth", value);
|
|
2690
|
+
if (next === this.settings.fluidDepth) return;
|
|
2691
|
+
this.settings.fluidDepth = next;
|
|
2692
|
+
writeSetting("fluidDepth", next);
|
|
2693
|
+
if (this.enabled) this.applyFluidPalettes();
|
|
2694
|
+
}
|
|
2695
|
+
/** Set the background brightness (0-100: 0 = pure black, 50 = transparent, 100 = pure white). */
|
|
2696
|
+
setBgBrightness(value) {
|
|
2697
|
+
const next = clampSetting("bgBrightness", value);
|
|
2698
|
+
if (next === this.settings.bgBrightness) return;
|
|
2699
|
+
this.settings.bgBrightness = next;
|
|
2700
|
+
writeSetting("bgBrightness", next);
|
|
2701
|
+
if (this.enabled) this.applySettings();
|
|
2702
|
+
}
|
|
2703
|
+
/** Set the backdrop source (fluid board or custom wallpaper). */
|
|
2704
|
+
setBackground(value) {
|
|
2705
|
+
if (value === this.settings.background) return;
|
|
2706
|
+
this.settings.background = value;
|
|
2707
|
+
writeBackground(value);
|
|
2708
|
+
if (this.enabled) this.applySettings();
|
|
2709
|
+
}
|
|
2710
|
+
/** Set the wallpaper image (a data URL; empty clears it) or a large video
|
|
2711
|
+
* (`idb:<id>` marker whose blob lives in IndexedDB). */
|
|
2712
|
+
setWallpaper(value) {
|
|
2713
|
+
const previous = this.settings.wallpaper;
|
|
2714
|
+
this.settings.wallpaper = value;
|
|
2715
|
+
writeWallpaper(value);
|
|
2716
|
+
if (previous.startsWith("idb:") && value !== previous) {
|
|
2717
|
+
void deleteVideoBlob(previous.slice(4));
|
|
2718
|
+
}
|
|
2719
|
+
if (!value.startsWith("idb:") && this.videoObjectUrl !== void 0) {
|
|
2720
|
+
URL.revokeObjectURL(this.videoObjectUrl);
|
|
2721
|
+
this.videoObjectUrl = void 0;
|
|
2722
|
+
this.videoBlobId = void 0;
|
|
2723
|
+
}
|
|
2724
|
+
if (this.enabled) this.applySettings();
|
|
2725
|
+
}
|
|
2726
|
+
/** Set the particle-whale flag (chat-area center decoration). */
|
|
2727
|
+
setWhale(value) {
|
|
2728
|
+
if (value === this.settings.whale) return;
|
|
2729
|
+
this.settings.whale = value;
|
|
2730
|
+
writeWhale(value);
|
|
2731
|
+
if (this.enabled) this.syncWhale();
|
|
2732
|
+
}
|
|
2733
|
+
/** Set the ambient marine-life flag (fish / bubbles / plankton). */
|
|
2734
|
+
setCritters(value) {
|
|
2735
|
+
if (value === this.settings.critters) return;
|
|
2736
|
+
this.settings.critters = value;
|
|
2737
|
+
writeCritters(value);
|
|
2738
|
+
if (this.enabled) this.applySettings();
|
|
2739
|
+
}
|
|
2740
|
+
/** Set the interactive-mesh flag (dot-grid decoration). */
|
|
2741
|
+
setMesh(value) {
|
|
2742
|
+
if (value === this.settings.mesh) return;
|
|
2743
|
+
this.settings.mesh = value;
|
|
2744
|
+
writeMesh(value);
|
|
2745
|
+
if (this.enabled) this.syncMesh();
|
|
2746
|
+
}
|
|
2747
|
+
/** Set the cursor-spotlight flag (pointer-tracking glass glow). */
|
|
2748
|
+
setSpotlight(value) {
|
|
2749
|
+
if (value === this.settings.spotlight) return;
|
|
2750
|
+
this.settings.spotlight = value;
|
|
2751
|
+
writeSpotlight(value);
|
|
2752
|
+
if (this.enabled) this.applySettings();
|
|
2753
|
+
}
|
|
2754
|
+
/** Set the hover-press flag (pane sinks a touch under the cursor). */
|
|
2755
|
+
setPress(value) {
|
|
2756
|
+
if (value === this.settings.press) return;
|
|
2757
|
+
this.settings.press = value;
|
|
2758
|
+
writePress(value);
|
|
2759
|
+
if (this.enabled) this.applySettings();
|
|
2760
|
+
}
|
|
2761
|
+
/** Set the wallpaper blur radius (px). */
|
|
2762
|
+
setWallpaperBlur(value) {
|
|
2763
|
+
const next = clampSetting("wallpaperBlur", value);
|
|
2764
|
+
if (next === this.settings.wallpaperBlur) return;
|
|
2765
|
+
this.settings.wallpaperBlur = next;
|
|
2766
|
+
writeSetting("wallpaperBlur", next);
|
|
2767
|
+
if (this.enabled) this.applySettings();
|
|
2768
|
+
}
|
|
2769
|
+
/** Set the wallpaper frost veil (0-100). */
|
|
2770
|
+
setWallpaperFrost(value) {
|
|
2771
|
+
const next = clampSetting("wallpaperFrost", value);
|
|
2772
|
+
if (next === this.settings.wallpaperFrost) return;
|
|
2773
|
+
this.settings.wallpaperFrost = next;
|
|
2774
|
+
writeSetting("wallpaperFrost", next);
|
|
2775
|
+
if (this.enabled) this.applySettings();
|
|
2776
|
+
}
|
|
2777
|
+
/** Set the video wallpaper blur radius (px). */
|
|
2778
|
+
setVideoBlur(value) {
|
|
2779
|
+
const next = clampSetting("videoBlur", value);
|
|
2780
|
+
if (next === this.settings.videoBlur) return;
|
|
2781
|
+
this.settings.videoBlur = next;
|
|
2782
|
+
writeSetting("videoBlur", next);
|
|
2783
|
+
if (this.enabled) this.applySettings();
|
|
2784
|
+
}
|
|
2785
|
+
/** Set the video wallpaper brightness (0-100, 100 = fully lit). */
|
|
2786
|
+
setVideoBrightness(value) {
|
|
2787
|
+
const next = clampSetting("videoBrightness", value);
|
|
2788
|
+
if (next === this.settings.videoBrightness) return;
|
|
2789
|
+
this.settings.videoBrightness = next;
|
|
2790
|
+
writeSetting("videoBrightness", next);
|
|
2791
|
+
if (this.enabled) this.applySettings();
|
|
2792
|
+
}
|
|
2793
|
+
/** After the user re-grants file access (选择视频 click on an fsa: video),
|
|
2794
|
+
* drop the mount guard and re-apply so the file is re-read and played. */
|
|
2795
|
+
authorizeVideo() {
|
|
2796
|
+
if (this.videoObjectUrl !== void 0) {
|
|
2797
|
+
URL.revokeObjectURL(this.videoObjectUrl);
|
|
2798
|
+
this.videoObjectUrl = void 0;
|
|
2799
|
+
}
|
|
2800
|
+
this.videoBlobId = void 0;
|
|
2801
|
+
if (this.enabled) this.applySettings();
|
|
2802
|
+
}
|
|
2803
|
+
sync() {
|
|
2804
|
+
if (this.enabled) this.mount();
|
|
2805
|
+
else this.unmount();
|
|
2806
|
+
}
|
|
2807
|
+
/** Write the knob-driven CSS variables and mode attributes onto <html>. */
|
|
2808
|
+
applySettings() {
|
|
2809
|
+
const style = document.documentElement.style;
|
|
2810
|
+
style.setProperty("--dsh-aqua-blur", `${this.settings.blur}px`);
|
|
2811
|
+
style.setProperty("--dsh-aqua-frost", String(Math.min(this.settings.frost / 50, 1.4)));
|
|
2812
|
+
style.setProperty("--dsh-aqua-surface-frost", String(Math.min((this.settings.frost + 20) / 50, 1.4)));
|
|
2813
|
+
const glowHue = ((this.settings.fluidHue + HUE_BASE) % 360 + 360) % 360;
|
|
2814
|
+
style.setProperty("--dsh-aqua-spot-color", this.dark ? `hsla(${glowHue}, 90%, 62%, 0.17)` : `hsla(${glowHue}, 90%, 45%, 0.16)`);
|
|
2815
|
+
style.setProperty("--dsh-aqua-wallpaper-blur", `${this.settings.wallpaperBlur}px`);
|
|
2816
|
+
style.setProperty("--dsh-aqua-wallpaper-frost", String(this.settings.wallpaperFrost / 100));
|
|
2817
|
+
style.setProperty("--dsh-aqua-video-blur", `${this.settings.videoBlur}px`);
|
|
2818
|
+
style.setProperty("--dsh-aqua-video-dim", String((100 - this.settings.videoBrightness) / 100 * 0.65));
|
|
2819
|
+
const dark = this.dark;
|
|
2820
|
+
style.setProperty("--dsh-aqua-brightness-black", String(dark ? Math.max(0, (50 - this.settings.bgBrightness) / 50) : 0));
|
|
2821
|
+
style.setProperty("--dsh-aqua-brightness-white", String(dark ? 0 : Math.max(0, (this.settings.bgBrightness - 50) / 50)));
|
|
2822
|
+
const compat = this.settings.mode === "compat";
|
|
2823
|
+
document.documentElement.toggleAttribute("data-dsh-float", !compat);
|
|
2824
|
+
document.documentElement.toggleAttribute("data-dsh-compat", compat);
|
|
2825
|
+
document.documentElement.toggleAttribute(SPOTLIGHT_ATTRIBUTE, !compat && this.settings.spotlight);
|
|
2826
|
+
document.documentElement.toggleAttribute(PRESS_ATTRIBUTE, !compat && this.settings.press);
|
|
2827
|
+
const ambient = document.querySelector("[data-dsh-aqua-ambient]");
|
|
2828
|
+
if (ambient !== null) ambient.dataset.background = this.settings.background;
|
|
2829
|
+
if (ambient !== null) ambient.dataset.critters = this.settings.critters ? "on" : "off";
|
|
2830
|
+
const wallpaper = this.settings.wallpaper;
|
|
2831
|
+
const isVideo = wallpaper.startsWith("data:video/") || wallpaper.startsWith("idb:") || wallpaper.startsWith("fsa:");
|
|
2832
|
+
const wallpaperLayer = document.querySelector("[data-dsh-aqua-wallpaper-layer]");
|
|
2833
|
+
if (wallpaperLayer !== null) {
|
|
2834
|
+
wallpaperLayer.dataset.background = this.settings.background;
|
|
2835
|
+
wallpaperLayer.dataset.media = isVideo ? "video" : "image";
|
|
2836
|
+
}
|
|
2837
|
+
const wallpaperOn = this.settings.background === "wallpaper" && wallpaper !== "";
|
|
2838
|
+
document.documentElement.toggleAttribute("data-dsh-aqua-wallpaper", wallpaperOn);
|
|
2839
|
+
if (wallpaperOn) {
|
|
2840
|
+
document.documentElement.setAttribute("data-dsh-aqua-media", isVideo ? "video" : "image");
|
|
2841
|
+
} else {
|
|
2842
|
+
document.documentElement.removeAttribute("data-dsh-aqua-media");
|
|
2843
|
+
}
|
|
2844
|
+
const img = document.querySelector("[data-dsh-aqua-wallpaper-img]");
|
|
2845
|
+
if (img !== null) {
|
|
2846
|
+
if (this.settings.background === "wallpaper" && wallpaper !== "" && !isVideo) {
|
|
2847
|
+
img.src = wallpaper;
|
|
2848
|
+
} else {
|
|
2849
|
+
img.removeAttribute("src");
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
const video = document.querySelector("[data-dsh-aqua-wallpaper-video]");
|
|
2853
|
+
if (video !== null) {
|
|
2854
|
+
if (this.settings.background === "wallpaper" && isVideo) {
|
|
2855
|
+
if (wallpaper.startsWith("idb:")) {
|
|
2856
|
+
const id5 = wallpaper.slice(4);
|
|
2857
|
+
if (this.videoBlobId === id5 && this.videoObjectUrl !== void 0) {
|
|
2858
|
+
} else {
|
|
2859
|
+
void loadVideoBlob(id5).then((blob) => {
|
|
2860
|
+
if (blob === null) return;
|
|
2861
|
+
if (this.settings.wallpaper !== wallpaper) return;
|
|
2862
|
+
const url = URL.createObjectURL(blob);
|
|
2863
|
+
if (this.videoObjectUrl !== void 0) URL.revokeObjectURL(this.videoObjectUrl);
|
|
2864
|
+
this.videoObjectUrl = url;
|
|
2865
|
+
this.videoBlobId = id5;
|
|
2866
|
+
video.setAttribute("src", url);
|
|
2867
|
+
this.configureWallpaperVideo(video);
|
|
2868
|
+
});
|
|
2869
|
+
}
|
|
2870
|
+
} else if (wallpaper.startsWith("fsa:")) {
|
|
2871
|
+
if (this.videoBlobId === wallpaper && this.videoObjectUrl !== void 0) {
|
|
2872
|
+
} else {
|
|
2873
|
+
void loadVideoHandle().then(async (handle) => {
|
|
2874
|
+
if (handle === null) return;
|
|
2875
|
+
if (this.settings.wallpaper !== wallpaper) return;
|
|
2876
|
+
try {
|
|
2877
|
+
const permission = await handle.queryPermission({ mode: "read" });
|
|
2878
|
+
if (permission !== "granted") return;
|
|
2879
|
+
const file = await handle.getFile();
|
|
2880
|
+
const url = URL.createObjectURL(file);
|
|
2881
|
+
if (this.videoObjectUrl !== void 0) URL.revokeObjectURL(this.videoObjectUrl);
|
|
2882
|
+
this.videoObjectUrl = url;
|
|
2883
|
+
this.videoBlobId = wallpaper;
|
|
2884
|
+
video.setAttribute("src", url);
|
|
2885
|
+
this.configureWallpaperVideo(video);
|
|
2886
|
+
} catch {
|
|
2887
|
+
}
|
|
2888
|
+
});
|
|
2889
|
+
}
|
|
2890
|
+
} else if (video.getAttribute("src") !== wallpaper) {
|
|
2891
|
+
video.setAttribute("src", wallpaper);
|
|
2892
|
+
this.configureWallpaperVideo(video);
|
|
2893
|
+
}
|
|
2894
|
+
} else {
|
|
2895
|
+
video.pause();
|
|
2896
|
+
video.removeAttribute("src");
|
|
2897
|
+
video.load();
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
/** The wallpaper plays as a plain <video> element (the browser's own
|
|
2902
|
+
* decoder, no player chrome at all): looping on, cover fill via CSS, and
|
|
2903
|
+
* autoplay with a muted fallback where policy requires it. A direct
|
|
2904
|
+
* element (not an iframe) keeps backdrop-filter working over it, so the
|
|
2905
|
+
* glass panels stay frosted above the video. */
|
|
2906
|
+
configureWallpaperVideo(video) {
|
|
2907
|
+
video.loop = true;
|
|
2908
|
+
if (!video.paused) return;
|
|
2909
|
+
void video.play().catch(() => {
|
|
2910
|
+
video.muted = true;
|
|
2911
|
+
void video.play().catch(() => {
|
|
2912
|
+
});
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
/** Apply the mode's token layer (floating palette, or translucent compat). */
|
|
2916
|
+
applyTokens() {
|
|
2917
|
+
this.tokenDisposer?.();
|
|
2918
|
+
this.tokenDisposer = this.ctx.theme.overrideTokens(
|
|
2919
|
+
OVERRIDE_SOURCE,
|
|
2920
|
+
this.settings.mode === "compat" ? COMPAT_TOKEN_OVERRIDES : AQUA_TOKEN_OVERRIDES
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
mount() {
|
|
2924
|
+
document.documentElement.setAttribute(AQUA_ATTRIBUTE, "");
|
|
2925
|
+
ensureAmbientScene();
|
|
2926
|
+
ensurePageFades();
|
|
2927
|
+
this.applySettings();
|
|
2928
|
+
this.applyTokens();
|
|
2929
|
+
this.startSeamStamper();
|
|
2930
|
+
this.mountFluid();
|
|
2931
|
+
this.startSpotlightFeed();
|
|
2932
|
+
this.syncWhale();
|
|
2933
|
+
this.syncMesh();
|
|
2934
|
+
}
|
|
2935
|
+
/** Mount or drop the particle whale to match enabled + the whale flag. */
|
|
2936
|
+
syncWhale() {
|
|
2937
|
+
if (this.enabled && this.settings.whale) {
|
|
2938
|
+
if (this.whaleHandle !== void 0) return;
|
|
2939
|
+
const ambient = document.querySelector("[data-dsh-aqua-ambient]");
|
|
2940
|
+
if (ambient === null) return;
|
|
2941
|
+
this.whaleHandle = mountWhale(ambient, this.dark);
|
|
2942
|
+
} else {
|
|
2943
|
+
this.whaleHandle?.dispose();
|
|
2944
|
+
this.whaleHandle = void 0;
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
/** Mount or drop the interactive mesh to match enabled + the mesh flag. */
|
|
2948
|
+
syncMesh() {
|
|
2949
|
+
if (this.enabled && this.settings.mesh) {
|
|
2950
|
+
if (this.meshHandle !== void 0) return;
|
|
2951
|
+
const ambient = document.querySelector("[data-dsh-aqua-ambient]");
|
|
2952
|
+
if (ambient === null) return;
|
|
2953
|
+
this.meshHandle = mountMesh(ambient);
|
|
2954
|
+
} else {
|
|
2955
|
+
this.meshHandle?.dispose();
|
|
2956
|
+
this.meshHandle = void 0;
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
unmount() {
|
|
2960
|
+
document.documentElement.removeAttribute(AQUA_ATTRIBUTE);
|
|
2961
|
+
document.documentElement.removeAttribute("data-dsh-float");
|
|
2962
|
+
document.documentElement.removeAttribute("data-dsh-compat");
|
|
2963
|
+
document.documentElement.removeAttribute("data-dsh-aqua-wallpaper");
|
|
2964
|
+
document.documentElement.removeAttribute("data-dsh-aqua-media");
|
|
2965
|
+
document.documentElement.removeAttribute(SPOTLIGHT_ATTRIBUTE);
|
|
2966
|
+
document.documentElement.removeAttribute(PRESS_ATTRIBUTE);
|
|
2967
|
+
this.spotlightDisposer?.();
|
|
2968
|
+
this.spotlightDisposer = void 0;
|
|
2969
|
+
this.whaleHandle?.dispose();
|
|
2970
|
+
this.whaleHandle = void 0;
|
|
2971
|
+
this.meshHandle?.dispose();
|
|
2972
|
+
this.meshHandle = void 0;
|
|
2973
|
+
this.tokenDisposer?.();
|
|
2974
|
+
this.tokenDisposer = void 0;
|
|
2975
|
+
if (this.videoObjectUrl !== void 0) {
|
|
2976
|
+
URL.revokeObjectURL(this.videoObjectUrl);
|
|
2977
|
+
this.videoObjectUrl = void 0;
|
|
2978
|
+
this.videoBlobId = void 0;
|
|
2979
|
+
}
|
|
2980
|
+
this.teardownFluid();
|
|
2981
|
+
removeAmbientScene();
|
|
2982
|
+
removePageFades();
|
|
2983
|
+
this.seamDisposer?.();
|
|
2984
|
+
this.seamDisposer = void 0;
|
|
2985
|
+
}
|
|
2986
|
+
/** Attach the fluid shader and the interaction feeds. */
|
|
2987
|
+
mountFluid() {
|
|
2988
|
+
const mainCanvas = document.querySelector("[data-dsh-aqua-fluid-canvas]");
|
|
2989
|
+
try {
|
|
2990
|
+
if (mainCanvas !== null) this.mainFluid = attachFluidShader(mainCanvas, this.fluidParams());
|
|
2991
|
+
this.applyFluidPalettes();
|
|
2992
|
+
if (this.mainFluid !== void 0 && mainCanvas !== null) {
|
|
2993
|
+
this.interactionDisposer = attachFluidInteractions({
|
|
2994
|
+
main: this.mainFluid,
|
|
2995
|
+
mainCanvas
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
} catch {
|
|
2999
|
+
this.mainFluid = void 0;
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
teardownFluid() {
|
|
3003
|
+
this.interactionDisposer?.();
|
|
3004
|
+
this.interactionDisposer = void 0;
|
|
3005
|
+
this.mainFluid?.dispose();
|
|
3006
|
+
this.mainFluid = void 0;
|
|
3007
|
+
}
|
|
3008
|
+
fluidParams() {
|
|
3009
|
+
return { ...SITE_FLUID_PARAMS, ...fluidToneColors(this.dark, this.settings.fluidHue, this.settings.fluidDepth) };
|
|
3010
|
+
}
|
|
3011
|
+
applyFluidPalettes() {
|
|
3012
|
+
this.mainFluid?.setParams(this.fluidParams());
|
|
3013
|
+
}
|
|
3014
|
+
/** Stamp the data-* seams the stylesheet keys off (self-contained mode). */
|
|
3015
|
+
startSeamStamper() {
|
|
3016
|
+
if (this.seamDisposer !== void 0) return;
|
|
3017
|
+
this.seamDisposer = startSeamStamper();
|
|
3018
|
+
}
|
|
3019
|
+
/** Attach the cursor-spotlight pointer feeds (idempotent per mount). */
|
|
3020
|
+
startSpotlightFeed() {
|
|
3021
|
+
if (this.spotlightDisposer !== void 0) return;
|
|
3022
|
+
this.spotlightDisposer = startSpotlight();
|
|
3023
|
+
}
|
|
3024
|
+
};
|
|
3025
|
+
|
|
3026
|
+
// src/client/aqua.module.css
|
|
3027
|
+
var id3 = "@deepseek-ai/dsh-client-ui-aqua/aqua.module.css";
|
|
3028
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=" + JSON.stringify(id3) + "]")) {
|
|
3029
|
+
const tag = document.createElement("style");
|
|
3030
|
+
tag.dataset.plugin = "dsh-transparent-ui";
|
|
3031
|
+
tag.dataset.pluginCss = id3;
|
|
3032
|
+
tag.textContent = `[data-dsh-aqua] body{background:var(--dsw-alias-bg-base);isolation:isolate}[data-dsh-aqua]{--dsh-aqua-glass-card-light: color-mix(in srgb, rgb(255 255 255) calc(42% * var(--dsh-aqua-frost, 1)), transparent);--dsh-aqua-glass-card-dark: color-mix(in srgb, rgb(34 38 47) calc(50% * var(--dsh-aqua-frost, 1)), transparent)}[data-dsh-aqua] [data-dsh-frame],[data-dsh-aqua] [data-dsh-frame]>[class*=centerCol]{background:transparent}[data-dsh-aqua] [data-phase],[data-dsh-aqua] [data-dsh-details]{background:transparent}[data-dsh-float] [data-phase=active] header{position:relative;z-index:8}[data-dsh-float] [class*=banner]{position:static}[data-dsh-float] [data-phase=active] :has(>[data-conversation-scroll]){position:relative;z-index:0}[data-dsh-float] [data-phase=active] [data-conversation-scroll]{margin-top:calc(0px - var(--dsh-aqua-header-overlap, 0px));padding-top:calc(var(--dsh-aqua-header-overlap, 0px) + 12px)}[data-dsh-aqua] header{position:relative;z-index:10;pointer-events:auto}html[data-dsh-aqua][data-platform] header[data-window-drag],html[data-dsh-aqua][data-platform] header[data-window-drag] *{-webkit-app-region:no-drag}[data-dsh-aqua] header :is(button,a,input,select,[role=button]){pointer-events:auto}[data-dsh-aqua] [data-phase] [class*=composerSeat][class*=composerSeat]{background:none}[data-dsh-aqua] [data-dsh-aqua-ambient]{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden;background:transparent}[data-dsh-aqua] body[data-ds-dark-theme] [data-dsh-aqua-ambient]{background:transparent}[data-dsh-aqua] [data-dsh-aqua-ambient]:after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background-image:linear-gradient(rgba(255,255,255,var(--dsh-aqua-brightness-white, 0)),rgba(255,255,255,var(--dsh-aqua-brightness-white, 0))),linear-gradient(rgba(0,0,0,var(--dsh-aqua-brightness-black, 0)),rgba(0,0,0,var(--dsh-aqua-brightness-black, 0)))}@media(prefers-reduced-motion:no-preference){[data-dsh-aqua] [data-dsh-aqua-ambient]{animation:aqua_dsh-aqua-breathe 9s var(--ds-ease-in-out) infinite alternate}}@keyframes aqua_dsh-aqua-breathe{0%{opacity:.86}to{opacity:1}}[data-dsh-aqua] [data-dsh-aqua-fluid-canvas]{position:absolute;z-index:0;inset:0 auto 0 var(--dsh-aqua-fluid-left, 0px);width:var(--dsh-aqua-fluid-width, 0px);height:100%;pointer-events:none}[data-dsh-aqua] [data-dsh-aqua-wallpaper]{position:fixed;inset:0;z-index:-1;overflow:hidden}[data-dsh-aqua] [data-dsh-aqua-wallpaper-img]{width:100%;height:100%;object-fit:cover}[data-dsh-aqua] [data-dsh-aqua-wallpaper-video]{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border:0;pointer-events:none;filter:blur(var(--dsh-aqua-video-blur, 0px))}[data-dsh-aqua] [data-dsh-aqua-wallpaper-img]{filter:blur(var(--dsh-aqua-wallpaper-blur, 0px))}[data-dsh-aqua] [data-dsh-aqua-wallpaper]:after{content:"";position:absolute;inset:0;background:rgb(255 255 255 / var(--dsh-aqua-wallpaper-frost, 0));pointer-events:none}[data-dsh-aqua] body[data-ds-dark-theme] [data-dsh-aqua-wallpaper]:after{background:rgb(12 18 27 / var(--dsh-aqua-wallpaper-frost, 0))}[data-dsh-aqua] [data-dsh-aqua-wallpaper][data-media=video]:after{display:block;background:rgb(255 255 255 / calc(var(--dsh-aqua-video-dim, .36) * 1.3))}[data-dsh-aqua] body[data-ds-dark-theme] [data-dsh-aqua-wallpaper][data-media=video]:after{background:rgb(8 12 20 / var(--dsh-aqua-video-dim, .36))}[data-dsh-aqua] [data-dsh-aqua-whale]{position:absolute;transform:translate(-50%,-50%);pointer-events:none;mix-blend-mode:screen;opacity:.92}[data-dsh-aqua] [data-dsh-aqua-whale][data-scheme=light]{mix-blend-mode:multiply}[data-dsh-aqua] [data-dsh-aqua-whale] canvas{display:block;width:100%;height:100%}[data-dsh-aqua] [data-dsh-aqua-ambient][data-background=wallpaper] [data-dsh-aqua-fluid-canvas],[data-dsh-aqua] [data-dsh-aqua-wallpaper][data-background=fluid]{display:none}[data-dsh-aqua] [data-dsh-aqua-mesh]{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}[data-dsh-aqua] [data-dsh-aqua-whale],[data-dsh-aqua] [data-dsh-aqua-mesh],[data-dsh-aqua] [data-aqua-critter]{z-index:2}[data-dsh-aqua] [data-dsh-aqua-ambient][data-critters=off] [data-aqua-critter]{display:none}[data-dsh-aqua] [data-aqua-critter]{position:absolute;color:#7ea4df;opacity:.22}[data-dsh-aqua] [data-aqua-critter=fish]{animation:aqua_dsh-aqua-fish-swim 12s var(--ds-ease-in-out) infinite}[data-dsh-aqua] [data-aqua-critter=fish-left]{animation:aqua_dsh-aqua-fish-swim-left 16s var(--ds-ease-in-out) infinite}[data-dsh-aqua] [data-aqua-critter=bubble]{color:#a9c6ef;opacity:0;animation:aqua_dsh-aqua-bubble-rise 9s ease-in infinite}[data-dsh-aqua] [data-aqua-critter=plankton]{color:#7ea4df;animation:aqua_dsh-aqua-plankton 5s ease-in-out infinite}@keyframes aqua_dsh-aqua-fish-swim{0%{transform:translateZ(0) rotate(-5deg)}30%{transform:translate3d(40px,-15px,0) rotate(4deg)}70%{transform:translate3d(52px,-18px,0) rotate(3deg)}to{transform:translateZ(0) rotate(-5deg)}}@keyframes aqua_dsh-aqua-fish-swim-left{0%{transform:translateZ(0) scaleX(-1) rotate(-5deg)}30%{transform:translate3d(-34px,-12px,0) scaleX(-1) rotate(4deg)}70%{transform:translate3d(-44px,-15px,0) scaleX(-1) rotate(3deg)}to{transform:translateZ(0) scaleX(-1) rotate(-5deg)}}@keyframes aqua_dsh-aqua-bubble-rise{0%{transform:translateZ(0);opacity:0}10%{opacity:.5}to{transform:translate3d(8px,-150px,0);opacity:0}}@keyframes aqua_dsh-aqua-plankton{0%,to{opacity:.1}50%{opacity:.38}}[data-dsh-float] [role=menu],[data-dsh-float] [role=dialog],[data-dsh-float] [role=alert],[data-dsh-float] [data-dsh-surface]{border-radius:14px}[data-dsh-float] [data-dsh-surface]{background:color-mix(in srgb,rgb(255 255 255) calc(62% * var(--dsh-aqua-surface-frost, 1)),transparent);border:1px solid rgba(19,45,83,.16);box-shadow:inset 0 1px #ffffff73;backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] [data-dsh-surface]:hover:not(:disabled){background:color-mix(in srgb,rgb(255 255 255) calc(74% * var(--dsh-aqua-surface-frost, 1)),transparent)}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-surface]{background:color-mix(in srgb,rgb(42 46 56) calc(62% * var(--dsh-aqua-surface-frost, 1)),transparent);border-color:#94b4dc33;box-shadow:inset 0 1px #ffffff14}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-surface]:hover:not(:disabled){background:color-mix(in srgb,rgb(54 58 70) calc(70% * var(--dsh-aqua-surface-frost, 1)),transparent)}[data-dsh-float] [role=menuitem],[data-dsh-float] [role=tooltip],[data-dsh-float] [class*=pill]{border-radius:8px}[data-dsh-float] button[class*=button]{border-radius:10px}[data-dsh-float] [class*=iconButton],[data-dsh-float] [class*=searchButton]{border-radius:8px}[data-dsh-float] [data-dsh-add]{background:color-mix(in srgb,rgb(255 255 255) calc(40% * var(--dsh-aqua-frost, 1)),transparent);border:1px solid rgba(19,45,83,.18);box-shadow:inset 0 1px #ffffff80;backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] [data-dsh-add]:hover:not(:disabled){background:color-mix(in srgb,rgb(255 255 255) calc(58% * var(--dsh-aqua-frost, 1)),transparent)}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-add]{background:color-mix(in srgb,rgb(42 46 56) calc(40% * var(--dsh-aqua-frost, 1)),transparent);border-color:#94b4dc40;box-shadow:inset 0 1px #ffffff14}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-add]:hover:not(:disabled){background:color-mix(in srgb,rgb(54 58 70) calc(52% * var(--dsh-aqua-frost, 1)),transparent)}[data-dsh-float] [class*=bubble]{border-radius:14px;border:1px solid rgba(19,45,83,.14);background:color-mix(in srgb,rgb(255 255 255) calc(42% * var(--dsh-aqua-frost, 1)),transparent);backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] body[data-ds-dark-theme] [class*=bubble]{border-color:#94b4dc24;background:color-mix(in srgb,rgb(0 0 0) calc(40% * var(--dsh-aqua-frost, 1)),transparent)}html[data-dsh-float][data-dsh-aqua-wallpaper][data-dsh-aqua-media=video] [class*=bubble]{background:color-mix(in srgb,rgb(255 255 255) 70%,transparent);border-color:#132d5333}html[data-dsh-float][data-dsh-aqua-wallpaper][data-dsh-aqua-media=video] body[data-ds-dark-theme] [class*=bubble]{background:color-mix(in srgb,rgb(0 0 0) 50%,transparent);border-color:#94b4dc38}[data-dsh-float] [class*=card]{border-radius:14px}[data-dsh-float] [data-composer-card],[data-dsh-float] [data-composer-card]:after{border-radius:24px}[data-dsh-float] [data-composer-card]{position:relative;z-index:8;background:var(--dsh-aqua-glass-card-light);border:1px solid rgba(19,45,83,.26);box-shadow:inset 0 1px #ffffff80,0 10px 36px #132d5329;backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] body[data-ds-dark-theme] [data-composer-card]{background:var(--dsh-aqua-glass-card-dark);border:1px solid rgba(148,180,220,.32);box-shadow:inset 0 1px #ffffff12,0 10px 36px #02060e80}[data-dsh-aqua][data-dsh-float] [data-dsh-inputbar]:has([data-dsh-stats]){width:calc(var(--dsh-chat-content-width) + 32px);max-width:none;margin:0 auto 12px;padding:0;border:1px solid rgba(19,45,83,.26);border-radius:24px;background:var(--dsh-aqua-glass-card-light);box-shadow:inset 0 1px #ffffff80,0 10px 36px #132d5329;backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-inputbar]:has([data-dsh-stats]){border-color:#94b4dc52;background:var(--dsh-aqua-glass-card-dark);box-shadow:inset 0 1px #ffffff12,0 10px 36px #02060e80}[data-dsh-float] [data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card]{border:none;border-radius:0;background:transparent;box-shadow:none;backdrop-filter:none}[data-dsh-float] [data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card]:after{display:none}[data-dsh-float] [data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{width:100%;max-width:none;margin:auto 0 0;min-height:24px;box-sizing:border-box;display:block;padding:2px 16px;border:none;border-top:1px solid rgba(19,45,83,.18);border-radius:0;background:transparent;box-shadow:none;backdrop-filter:none}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{border-top-color:#94b4dc3d}[data-dsh-float] [data-composer-card]:after{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='24' ry='24' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E");mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='24' ry='24' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E")}[data-dsh-float] [class*=block]{border-radius:14px;--dsl-code-block-border-radius: 14px;--dsl-diff-radius: 14px;--dsl-read-radius: 14px;--dsl-terminal-radius: 14px;--dsl-web-radius: 14px;--dsl-search-radius: 14px}[data-dsh-float] header{margin:12px 16px 0;padding:10px 16px 8px;border:1px solid rgba(19,45,83,.26);border-bottom-color:transparent;border-radius:20px;background:var(--dsh-aqua-glass-card-light);box-shadow:inset 0 1px #ffffff80,0 10px 34px #132d5329;backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] header:after{display:none}[data-dsh-float] body[data-ds-dark-theme] header{border-color:#94b4dc52;border-bottom-color:transparent;background:var(--dsh-aqua-glass-card-dark);box-shadow:inset 0 1px #ffffff12,0 8px 30px #02060e52}[data-dsh-float] [data-dsh-frame][data-sidebar-collapsed] header{margin-left:28px}[data-dsh-float] [class*=sidebarCol]{position:relative;z-index:9;margin:12px;padding:10px 12px 14px;border:1px solid rgba(19,45,83,.26);border-right:1px solid rgba(150,190,245,.65);border-radius:20px;background:var(--dsh-aqua-glass-card-light);backdrop-filter:blur(var(--dsh-aqua-blur, 14px));box-shadow:inset 0 1px #ffffff80,0 10px 34px #132d5329;overflow:hidden}[data-dsh-float] body[data-ds-dark-theme] [class*=sidebarCol]{border-color:#94b4dc52;border-right:1px solid rgba(148,180,220,.2);background:var(--dsh-aqua-glass-card-dark);box-shadow:inset 0 1px #ffffff12,0 8px 30px #02060e52}[data-dsh-float] [data-dsh-frame][data-sidebar-collapsed] [class*=sidebarCol]{margin:12px -12px 12px 12px;padding:0;border-radius:16px;transition:margin .15s var(--ds-ease-in-out),border-radius .15s var(--ds-ease-in-out),transform .1s ease-out}[data-dsh-float] [data-dsh-frame]:not([data-sidebar-collapsed]) [data-dsh-sidebar-root]{width:100%!important}[data-dsh-float] [data-dsh-trajectory]{margin:8px 16px 12px;width:calc(100% - 32px);height:calc(100% - 20px);border:1px solid rgba(19,45,83,.26);border-radius:20px;background:var(--dsh-aqua-glass-card-light);box-shadow:inset 0 1px #ffffff80,0 10px 34px #132d5329;backdrop-filter:blur(var(--dsh-aqua-blur, 14px));overflow:hidden}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-trajectory]{border-color:#94b4dc52;background:var(--dsh-aqua-glass-card-dark);box-shadow:inset 0 1px #ffffff12,0 8px 30px #02060e52}[data-dsh-float] [data-dsh-trajectory] [role=toolbar],[data-dsh-float] [data-dsh-trajectory] section[aria-label="Trajectory timeline"]{background:transparent}[data-dsh-float] [data-dsh-inputbar]:not([class*=hero]){padding-bottom:12px}[data-dsh-float] [data-dsh-stats]{position:relative;z-index:8;width:calc(var(--dsh-chat-content-width) + 32px);max-width:none;margin:0 auto;padding:2px 16px;border:1px solid rgba(19,45,83,.26);border-top:1px solid rgba(19,45,83,.18);border-radius:0 0 24px 24px;background:var(--dsh-aqua-glass-card-light);box-shadow:0 10px 36px #132d5329;backdrop-filter:blur(var(--dsh-aqua-blur, 14px));color:#262e3ee6}[data-dsh-float] body[data-ds-dark-theme] [data-dsh-stats]{border-color:#94b4dc52;border-top-color:#94b4dc3d;background:var(--dsh-aqua-glass-card-dark);box-shadow:0 10px 36px #02060e80;color:#e4ecf8eb}[data-dsh-float] [data-composer-card] textarea::placeholder{color:#37405480}[data-dsh-float] body[data-ds-dark-theme] [data-composer-card] textarea::placeholder{color:#cdd8ea85}[data-dsh-aqua][data-dsh-aqua-spotlight] [data-dsh-aqua-spot]{position:relative;isolation:isolate}[data-dsh-aqua] [data-dsh-aqua-glow]{display:none}[data-dsh-aqua][data-dsh-aqua-spotlight] [data-dsh-aqua-glow]{display:block;position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .3s ease;z-index:-1}[data-dsh-aqua][data-dsh-aqua-spotlight] [data-dsh-aqua-spot][data-spot-on] [data-dsh-aqua-glow]{opacity:1}[data-dsh-aqua][data-dsh-aqua-spotlight] [data-dsh-inputbar][data-dsh-aqua-spot] [data-dsh-aqua-glow]{border-radius:24px}[data-dsh-aqua][data-dsh-float] [class*=sidebarCol]:has([role=dialog]){backdrop-filter:none}[data-dsh-float][data-dsh-aqua-press] [data-dsh-aqua-spot]{transition:transform .1s ease-out}[data-dsh-aqua] body [role=dialog]{background:var(--dsh-aqua-glass-card-light);backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-aqua] body[data-ds-dark-theme] [role=dialog]{background:var(--dsh-aqua-glass-card-dark)}[data-dsh-aqua] body [data-shortcut-modal=settings]{background:var(--dsh-aqua-glass-card-light);backdrop-filter:blur(var(--dsh-aqua-blur, 14px));animation:none}[data-dsh-aqua] body[data-ds-dark-theme] [data-shortcut-modal=settings]{background:var(--dsh-aqua-glass-card-dark)}[data-dsh-float] [role=treeitem][aria-selected=true]{box-shadow:inset 2px 0 0 var(--dsw-specific-sidebar-nav-item-active-accent),0 0 16px #6e9be824}[data-dsh-float] button[class*=button]:hover:not(:disabled),[data-dsh-float] [role=menuitem]:hover:not(:disabled){box-shadow:0 0 12px #6e9be829,inset 0 0 0 1px #94b4dc38}[data-dsh-float] [role=menu]{background:color-mix(in srgb,rgb(255 255 255) calc(62% * var(--dsh-aqua-frost, 1)),transparent);backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-float] body[data-ds-dark-theme] [role=menu]{background:color-mix(in srgb,rgb(28 32 42) calc(68% * var(--dsh-aqua-frost, 1)),transparent)}[data-dsh-aqua] [data-dsh-aqua-fade]{position:fixed;left:0;right:0;height:13px;z-index:7;pointer-events:none;backdrop-filter:blur(5px);background:#fff3}[data-dsh-aqua] body[data-ds-dark-theme] [data-dsh-aqua-fade]{background:#00000026}[data-dsh-aqua] [data-dsh-aqua-fade=top]{top:0;-webkit-mask-image:linear-gradient(180deg,black 0%,transparent 100%);mask-image:linear-gradient(180deg,black 0%,transparent 100%)}[data-dsh-aqua] [data-dsh-aqua-fade=bottom]{bottom:0;-webkit-mask-image:linear-gradient(0deg,black 0%,transparent 100%);mask-image:linear-gradient(0deg,black 0%,transparent 100%)}[data-dsh-aqua] :focus-visible{outline:2px solid rgba(110,155,232,.85);outline-offset:1px}[data-dsh-aqua] ::selection{background:#6e9be859}[data-dsh-aqua] [data-conversation-scroll]{text-shadow:0 0 1px rgba(0,0,0,.4)}[data-dsh-aqua] body:not([data-ds-dark-theme]) [data-conversation-scroll]{text-shadow:0 0 1px rgba(255,255,255,.55),0 1px 2px rgba(19,45,83,.08)}[data-dsh-float] [role=dialog] h2{font-family:Space Grotesk Variable,"Noto Serif SC",Songti SC,STSong,SimSun,serif;font-weight:600;letter-spacing:.02em}[data-dsh-float] [role=treeitem]{font-family:Space Grotesk Variable,"Noto Serif SC",Songti SC,STSong,SimSun,serif;font-weight:500}[data-dsh-float] [data-phase=hero]{animation:aqua_dsh-aqua-hero-in .32s var(--ds-ease-in-out)}[data-dsh-float] [data-phase=active]{animation:aqua_dsh-aqua-active-in .3s var(--ds-ease-in-out)}[data-dsh-float] [data-testid^=view-]{animation:aqua_dsh-aqua-view-in .26s var(--ds-ease-in-out)}[data-dsh-float] [class*=userRow]{animation:aqua_dsh-aqua-rise .28s var(--ds-ease-in-out) both}[data-dsh-float] [data-tool]{animation:aqua_dsh-aqua-rise .3s var(--ds-ease-in-out) both}[data-dsh-float] [role=dialog]{animation:aqua_dsh-aqua-dialog-in .24s var(--ds-ease-in-out)}@keyframes aqua_dsh-aqua-hero-in{0%{opacity:0}}@keyframes aqua_dsh-aqua-active-in{0%{opacity:0}}@keyframes aqua_dsh-aqua-view-in{0%{opacity:0}}@keyframes aqua_dsh-aqua-rise{0%{opacity:0;transform:translateY(6px)}}@keyframes aqua_dsh-aqua-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.985)}}[data-dsh-compat] [role=menu],[data-dsh-compat] [role=tooltip],[data-dsh-compat] [class*=card],[data-dsh-compat] [class*=bubble],[data-dsh-compat] [class*=panel],[data-dsh-compat] [class*=popover],[data-dsh-compat] [class*=dropdown]{backdrop-filter:blur(12px)}[data-dsh-aqua] body :is(header,[data-composer-card],[data-shortcut-modal=settings]),[data-dsh-aqua] body [data-dsh-inputbar]:has([data-dsh-stats]){background:var(--dsh-aqua-glass-card-light);backdrop-filter:blur(var(--dsh-aqua-blur, 14px))}[data-dsh-aqua] body[data-ds-dark-theme] :is(header,[data-composer-card],[data-shortcut-modal=settings]),[data-dsh-aqua] body[data-ds-dark-theme] [data-dsh-inputbar]:has([data-dsh-stats]){background:var(--dsh-aqua-glass-card-dark)}[data-dsh-aqua] body [data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card],[data-dsh-aqua] body[data-ds-dark-theme] [data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card],[data-dsh-aqua] body [data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{background:transparent;backdrop-filter:none}@media(prefers-reduced-motion:reduce){[data-dsh-float] [data-phase=hero],[data-dsh-float] [data-phase=active],[data-dsh-float] [data-testid^=view-],[data-dsh-float] [class*=userRow],[data-dsh-float] [data-tool],[data-dsh-float] [role=dialog],[data-dsh-aqua] [data-dsh-aqua-ambient],[data-dsh-aqua] [data-aqua-critter]{animation:none}[data-dsh-aqua] [data-aqua-critter=bubble]{opacity:0}}
|
|
3033
|
+
`;
|
|
3034
|
+
document.head.appendChild(tag);
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
// src/client/fonts.module.css
|
|
3038
|
+
var id4 = "@deepseek-ai/dsh-client-ui-aqua/fonts.module.css";
|
|
3039
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=" + JSON.stringify(id4) + "]")) {
|
|
3040
|
+
const tag = document.createElement("style");
|
|
3041
|
+
tag.dataset.plugin = "dsh-transparent-ui";
|
|
3042
|
+
tag.dataset.pluginCss = id4;
|
|
3043
|
+
tag.textContent = '@font-face{font-family:Space Grotesk Variable;font-style:normal;font-display:swap;font-weight:300 700;src:url(data:font/woff2;base64,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) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Space Grotesk Variable;font-style:normal;font-display:swap;font-weight:300 700;src:url(data:font/woff2;base64,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) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Space Grotesk Variable;font-style:normal;font-display:swap;font-weight:300 700;src:url(data:font/woff2;base64,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) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}\n';
|
|
3044
|
+
document.head.appendChild(tag);
|
|
3045
|
+
}
|
|
3046
|
+
|
|
3047
|
+
// src/client/index.ts
|
|
3048
|
+
var inject = ["theme", "slots", "locale"];
|
|
3049
|
+
function apply(ctx) {
|
|
3050
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "ui-aqua: settings dictionaries");
|
|
3051
|
+
const layer = new AquaLayer(ctx);
|
|
3052
|
+
const pluginStore = createAquaRowStore();
|
|
3053
|
+
const appearanceStore = createAquaRowStore();
|
|
3054
|
+
let pluginBound;
|
|
3055
|
+
let appearanceBound;
|
|
3056
|
+
let revision = 0;
|
|
3057
|
+
const payload = () => {
|
|
3058
|
+
const s = layer.getSettings();
|
|
3059
|
+
return {
|
|
3060
|
+
enabled: layer.getEnabled(),
|
|
3061
|
+
mode: s.mode,
|
|
3062
|
+
blur: s.blur,
|
|
3063
|
+
frost: s.frost,
|
|
3064
|
+
fluidHue: s.fluidHue,
|
|
3065
|
+
fluidDepth: s.fluidDepth,
|
|
3066
|
+
bgBrightness: s.bgBrightness,
|
|
3067
|
+
dark: layer.getDark(),
|
|
3068
|
+
background: s.background,
|
|
3069
|
+
wallpaper: s.wallpaper,
|
|
3070
|
+
whale: s.whale,
|
|
3071
|
+
critters: s.critters,
|
|
3072
|
+
mesh: s.mesh,
|
|
3073
|
+
spotlight: s.spotlight,
|
|
3074
|
+
press: s.press,
|
|
3075
|
+
wallpaperBlur: s.wallpaperBlur,
|
|
3076
|
+
wallpaperFrost: s.wallpaperFrost,
|
|
3077
|
+
videoBlur: s.videoBlur,
|
|
3078
|
+
videoBrightness: s.videoBrightness
|
|
3079
|
+
};
|
|
3080
|
+
};
|
|
3081
|
+
const sync = () => {
|
|
3082
|
+
const next = payload();
|
|
3083
|
+
pluginBound?.sync(next, revision);
|
|
3084
|
+
appearanceBound?.sync(next, revision);
|
|
3085
|
+
revision += 1;
|
|
3086
|
+
};
|
|
3087
|
+
ctx.effect(() => ctx.on("theme/change", () => {
|
|
3088
|
+
sync();
|
|
3089
|
+
}), "ui-aqua: appearance scheme sync");
|
|
3090
|
+
const pluginInjected = (actions) => {
|
|
3091
|
+
pluginBound = actions;
|
|
3092
|
+
sync();
|
|
3093
|
+
return {
|
|
3094
|
+
setEnabled: (enabled) => {
|
|
3095
|
+
layer.setEnabled(enabled);
|
|
3096
|
+
sync();
|
|
3097
|
+
}
|
|
3098
|
+
};
|
|
3099
|
+
};
|
|
3100
|
+
const appearanceInjected = (actions) => {
|
|
3101
|
+
appearanceBound = actions;
|
|
3102
|
+
sync();
|
|
3103
|
+
return {
|
|
3104
|
+
setEnabled: (enabled) => {
|
|
3105
|
+
layer.setEnabled(enabled);
|
|
3106
|
+
sync();
|
|
3107
|
+
},
|
|
3108
|
+
setMode: (mode) => {
|
|
3109
|
+
layer.setMode(mode);
|
|
3110
|
+
sync();
|
|
3111
|
+
},
|
|
3112
|
+
setBlur: (blur) => {
|
|
3113
|
+
layer.setBlur(blur);
|
|
3114
|
+
sync();
|
|
3115
|
+
},
|
|
3116
|
+
setFrost: (frost) => {
|
|
3117
|
+
layer.setFrost(frost);
|
|
3118
|
+
sync();
|
|
3119
|
+
},
|
|
3120
|
+
setFluidHue: (fluidHue) => {
|
|
3121
|
+
layer.setFluidHue(fluidHue);
|
|
3122
|
+
sync();
|
|
3123
|
+
},
|
|
3124
|
+
setFluidDepth: (fluidDepth) => {
|
|
3125
|
+
layer.setFluidDepth(fluidDepth);
|
|
3126
|
+
sync();
|
|
3127
|
+
},
|
|
3128
|
+
setBgBrightness: (bgBrightness) => {
|
|
3129
|
+
layer.setBgBrightness(bgBrightness);
|
|
3130
|
+
sync();
|
|
3131
|
+
},
|
|
3132
|
+
setBackground: (background) => {
|
|
3133
|
+
layer.setBackground(background);
|
|
3134
|
+
sync();
|
|
3135
|
+
},
|
|
3136
|
+
setWallpaper: (wallpaper) => {
|
|
3137
|
+
layer.setWallpaper(wallpaper);
|
|
3138
|
+
sync();
|
|
3139
|
+
},
|
|
3140
|
+
setWhale: (whale) => {
|
|
3141
|
+
layer.setWhale(whale);
|
|
3142
|
+
sync();
|
|
3143
|
+
},
|
|
3144
|
+
setCritters: (critters) => {
|
|
3145
|
+
layer.setCritters(critters);
|
|
3146
|
+
sync();
|
|
3147
|
+
},
|
|
3148
|
+
setMesh: (mesh) => {
|
|
3149
|
+
layer.setMesh(mesh);
|
|
3150
|
+
sync();
|
|
3151
|
+
},
|
|
3152
|
+
setSpotlight: (spotlight) => {
|
|
3153
|
+
layer.setSpotlight(spotlight);
|
|
3154
|
+
sync();
|
|
3155
|
+
},
|
|
3156
|
+
setPress: (press) => {
|
|
3157
|
+
layer.setPress(press);
|
|
3158
|
+
sync();
|
|
3159
|
+
},
|
|
3160
|
+
setWallpaperBlur: (wallpaperBlur) => {
|
|
3161
|
+
layer.setWallpaperBlur(wallpaperBlur);
|
|
3162
|
+
sync();
|
|
3163
|
+
},
|
|
3164
|
+
setWallpaperFrost: (wallpaperFrost) => {
|
|
3165
|
+
layer.setWallpaperFrost(wallpaperFrost);
|
|
3166
|
+
sync();
|
|
3167
|
+
},
|
|
3168
|
+
setVideoBlur: (videoBlur) => {
|
|
3169
|
+
layer.setVideoBlur(videoBlur);
|
|
3170
|
+
sync();
|
|
3171
|
+
},
|
|
3172
|
+
setVideoBrightness: (videoBrightness) => {
|
|
3173
|
+
layer.setVideoBrightness(videoBrightness);
|
|
3174
|
+
sync();
|
|
3175
|
+
},
|
|
3176
|
+
authorizeVideo: () => {
|
|
3177
|
+
layer.authorizeVideo();
|
|
3178
|
+
}
|
|
3179
|
+
};
|
|
3180
|
+
};
|
|
3181
|
+
ctx.slots.inject("settings.general.item", () => ctx.slots.register({
|
|
3182
|
+
name: "settings.general.item",
|
|
3183
|
+
id: "aqua-toggle",
|
|
3184
|
+
order: 10.5,
|
|
3185
|
+
store: pluginStore,
|
|
3186
|
+
locale: NS,
|
|
3187
|
+
inject: pluginInjected
|
|
3188
|
+
}, AquaPluginCard));
|
|
3189
|
+
ctx.slots.inject("settings.general.item", () => ctx.slots.register({
|
|
3190
|
+
name: "settings.general.item",
|
|
3191
|
+
id: "aqua",
|
|
3192
|
+
order: 11,
|
|
3193
|
+
store: appearanceStore,
|
|
3194
|
+
locale: NS,
|
|
3195
|
+
inject: appearanceInjected
|
|
3196
|
+
}, AquaAppearanceRow));
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3199
|
+
return module.exports;
|
|
3200
|
+
}
|
|
3201
|
+
});
|