dsh-background-by-model 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -3
- package/README.zh.md +25 -3
- package/lib/client.js +421 -292
- package/lib/client.js.map +1 -1
- package/lib/index.js +159 -100
- package/package.json +8 -8
package/lib/client.js
CHANGED
|
@@ -32,31 +32,30 @@ window.__ModuleLoader__.load({
|
|
|
32
32
|
uiOpacity: "透明度",
|
|
33
33
|
uiBlur: "模糊度",
|
|
34
34
|
uiOpacityBg: "主背景",
|
|
35
|
-
uiOpacitySide: "
|
|
36
|
-
uiOpacityCard: "
|
|
35
|
+
uiOpacitySide: "左侧栏",
|
|
36
|
+
uiOpacityCard: "卡片与菜单面板",
|
|
37
37
|
uiOpacityInput: "输入框与控件",
|
|
38
38
|
uiSop: "设置界面透明度",
|
|
39
39
|
uiChatRegion: "对话文本框",
|
|
40
40
|
uiTrajectory: "轨迹页",
|
|
41
|
-
uiPreview: "
|
|
42
|
-
uiPreviewHint: "点开文件后出现在右侧的那一栏。透明度默认跟随「主背景」,拖动本卡片后单独生效;模糊会在主背景模糊之上再叠加一层",
|
|
43
|
-
uiScopeHint: "界面页的设置是全局的,所有模型共用",
|
|
44
|
-
statusTitle: "当前生效",
|
|
45
|
-
statusModel: "当前模型",
|
|
46
|
-
statusUnknown: "未检测到当前模型",
|
|
41
|
+
uiPreview: "右侧栏",
|
|
47
42
|
statusUnknownHint: "检测不到时一律使用第 1 条可用规则;切换一次模型或稍等片刻会自动重试",
|
|
48
|
-
statusSourceDefault: "宿主默认",
|
|
49
43
|
statusSourceDefaultHint: "只读到宿主默认模型,它不是本会话当前选择的模型;本会话的模型选择可用后会自动纠正",
|
|
50
44
|
statusNoteNoService: "仍未拿到会话服务(会话控制器晚于本插件加载),正在自动重试",
|
|
51
45
|
statusNoteNoSession: "会话服务已就绪,但还没有当前会话 id",
|
|
52
46
|
statusNoteNoProjection: "拿不到本会话的模型选择投影(binding / projections 不可用)",
|
|
53
47
|
statusNoteEmptySelection: "本会话的模型选择投影还没有值(切一次模型即可写入)",
|
|
54
|
-
statusNone: "还没有可用规则(规则需要启用并选择图片)",
|
|
55
|
-
statusHit: "命中",
|
|
56
|
-
statusFallback: "未命中 · 使用兜底",
|
|
57
|
-
statusRule: "规则",
|
|
58
48
|
rulesTitle: "规则列表",
|
|
59
49
|
rulesHint: "从上到下即为优先级。规则 1 同时兼任兜底:所有匹配串都没命中时使用它",
|
|
50
|
+
tryoutTitle: "匹配试跑",
|
|
51
|
+
tryoutPlaceholder: "输入模型名,如 deepseek-flash",
|
|
52
|
+
tryoutUseCurrent: "填入当前模型",
|
|
53
|
+
tryoutHit: "命中规则",
|
|
54
|
+
tryoutFallback: "无匹配 · 走兜底规则",
|
|
55
|
+
tryoutNone: "没有可用规则(规则需要启用并有图片)",
|
|
56
|
+
tryoutEmpty: "输入模型名即可试跑",
|
|
57
|
+
autoExtract: "选图后自动取主题色",
|
|
58
|
+
autoExtractHint: "只在规则还没有颜色时自动取色,绝不覆盖你手动选的颜色",
|
|
60
59
|
ruleAdd: "新增规则",
|
|
61
60
|
ruleFallbackBadge: "兜底",
|
|
62
61
|
ruleMatchLabel: "匹配串",
|
|
@@ -104,7 +103,7 @@ window.__ModuleLoader__.load({
|
|
|
104
103
|
extractColor: "从图片提取主题色",
|
|
105
104
|
extracting: "取色中…",
|
|
106
105
|
extractNoWp: "请先为该规则选择图片",
|
|
107
|
-
extractDone: "
|
|
106
|
+
extractDone: "已应用图片配色",
|
|
108
107
|
extractFail: "未在这张图里找到鲜明的颜色,请换一张",
|
|
109
108
|
eyedropper: "从图片取色",
|
|
110
109
|
pickerTitle: "从图片取色",
|
|
@@ -138,31 +137,30 @@ window.__ModuleLoader__.load({
|
|
|
138
137
|
uiOpacity: "Opacity",
|
|
139
138
|
uiBlur: "Blur",
|
|
140
139
|
uiOpacityBg: "Main background",
|
|
141
|
-
uiOpacitySide: "
|
|
142
|
-
uiOpacityCard: "Cards &
|
|
140
|
+
uiOpacitySide: "Left panel",
|
|
141
|
+
uiOpacityCard: "Cards & menus",
|
|
143
142
|
uiOpacityInput: "Input & controls",
|
|
144
143
|
uiSop: "Settings interface opacity",
|
|
145
144
|
uiChatRegion: "Conversation text frame",
|
|
146
145
|
uiTrajectory: "Trajectory view",
|
|
147
|
-
uiPreview: "
|
|
148
|
-
uiPreviewHint: "The column that slides in on the right when you open a file. Its opacity follows the Main background until you drag this card; its blur stacks on top of the Main background blur",
|
|
149
|
-
uiScopeHint: "Interface settings are global — every model shares them",
|
|
150
|
-
statusTitle: "Active now",
|
|
151
|
-
statusModel: "Current model",
|
|
152
|
-
statusUnknown: "No model detected",
|
|
146
|
+
uiPreview: "Right panel",
|
|
153
147
|
statusUnknownHint: "Without a detected model rule 1 is always used; switching the model once or waiting a moment retries automatically",
|
|
154
|
-
statusSourceDefault: "host default",
|
|
155
148
|
statusSourceDefaultHint: "Only the host-wide default model could be read — that is not necessarily this session's selection. It self-corrects once this session's model selection is available.",
|
|
156
149
|
statusNoteNoService: "The sessions service is not available yet (the session controller loads after this plugin); retrying automatically",
|
|
157
150
|
statusNoteNoSession: "The sessions service is up but reports no current session yet",
|
|
158
151
|
statusNoteNoProjection: "This session's model-selection projection is unreachable (no binding / projections)",
|
|
159
152
|
statusNoteEmptySelection: "The model-selection projection exists but carries no value yet (selecting a model once writes it)",
|
|
160
|
-
statusNone: "No usable rule yet (a rule needs to be enabled and have an image)",
|
|
161
|
-
statusHit: "matched",
|
|
162
|
-
statusFallback: "no match · using the fallback",
|
|
163
|
-
statusRule: "Rule",
|
|
164
153
|
rulesTitle: "Rules",
|
|
165
154
|
rulesHint: "Top to bottom is the priority. Rule 1 doubles as the fallback — it is used when no match string hits",
|
|
155
|
+
tryoutTitle: "Match test",
|
|
156
|
+
tryoutPlaceholder: "Type a model name, e.g. deepseek-flash",
|
|
157
|
+
tryoutUseCurrent: "Use current model",
|
|
158
|
+
tryoutHit: "matches rule",
|
|
159
|
+
tryoutFallback: "no match · fallback rule",
|
|
160
|
+
tryoutNone: "No usable rule (a rule needs to be enabled and have an image)",
|
|
161
|
+
tryoutEmpty: "Type a model name to test the list",
|
|
162
|
+
autoExtract: "Extract the theme color when an image is chosen",
|
|
163
|
+
autoExtractHint: "Only fills a rule that has no color yet — a color you picked is never overwritten",
|
|
166
164
|
ruleAdd: "Add rule",
|
|
167
165
|
ruleFallbackBadge: "fallback",
|
|
168
166
|
ruleMatchLabel: "Match",
|
|
@@ -210,7 +208,7 @@ window.__ModuleLoader__.load({
|
|
|
210
208
|
extractColor: "Extract from image",
|
|
211
209
|
extracting: "Extracting…",
|
|
212
210
|
extractNoWp: "Choose an image for this rule first",
|
|
213
|
-
extractDone: "Image
|
|
211
|
+
extractDone: "Image colors applied",
|
|
214
212
|
extractFail: "No vivid color found in this image, try another",
|
|
215
213
|
eyedropper: "Eyedropper",
|
|
216
214
|
pickerTitle: "Pick from image",
|
|
@@ -231,7 +229,7 @@ window.__ModuleLoader__.load({
|
|
|
231
229
|
footerTag: "Per-model wallpaper plugin"
|
|
232
230
|
};
|
|
233
231
|
//#endregion
|
|
234
|
-
//#region src/
|
|
232
|
+
//#region src/schema.ts
|
|
235
233
|
const DEFAULT_BG_STATE = {
|
|
236
234
|
zoom: 1,
|
|
237
235
|
x: 0,
|
|
@@ -239,6 +237,7 @@ window.__ModuleLoader__.load({
|
|
|
239
237
|
iw: 0,
|
|
240
238
|
ih: 0
|
|
241
239
|
};
|
|
240
|
+
/** Every accepted `bgMode`, in UI order. */
|
|
242
241
|
const BG_MODES$1 = [
|
|
243
242
|
"fit",
|
|
244
243
|
"fill",
|
|
@@ -246,6 +245,138 @@ window.__ModuleLoader__.load({
|
|
|
246
245
|
"tile",
|
|
247
246
|
"center"
|
|
248
247
|
];
|
|
248
|
+
/**
|
|
249
|
+
* Main interface opacities (0..1), global (Interface page):
|
|
250
|
+
* `bg` main background (`--dsw-alias-bg-base`)
|
|
251
|
+
* `sidebar` sidebar (`--dsw-specific-sidebar-fill`)
|
|
252
|
+
* `card` cards/panels (`--dsw-alias-bg-layer-1/2/3`, `--dsw-specific-menu`
|
|
253
|
+
* and its 0.1.7 alias `--dsw-menu-surface-fill`)
|
|
254
|
+
* `input` input/control surfaces (`--dsw-specific-input-major`)
|
|
255
|
+
*/
|
|
256
|
+
const PART_OPACITY_KEYS = [
|
|
257
|
+
"bg",
|
|
258
|
+
"sidebar",
|
|
259
|
+
"card",
|
|
260
|
+
"input"
|
|
261
|
+
];
|
|
262
|
+
const DEFAULT_PART_OPACITIES = {
|
|
263
|
+
bg: .85,
|
|
264
|
+
sidebar: .93,
|
|
265
|
+
card: 1,
|
|
266
|
+
input: 1
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* Interface blur (px, 0..60), global (Interface page):
|
|
270
|
+
* `bg` main background (AppFrame grid)
|
|
271
|
+
* `sidebar` sidebar column
|
|
272
|
+
* `card` cards/panels (center + details columns, dialog option panels)
|
|
273
|
+
* `settings` settings panel
|
|
274
|
+
* `chat` conversation text region (message column of the chat view)
|
|
275
|
+
* `trajectory` trajectory view surface
|
|
276
|
+
* `rightbar` file-preview panel — the right sidebar a file click opens
|
|
277
|
+
* `input` input/control surfaces ([data-composer-card], [data-cordis-panel])
|
|
278
|
+
*/
|
|
279
|
+
const PART_BLUR_KEYS = [
|
|
280
|
+
"bg",
|
|
281
|
+
"sidebar",
|
|
282
|
+
"card",
|
|
283
|
+
"settings",
|
|
284
|
+
"chat",
|
|
285
|
+
"trajectory",
|
|
286
|
+
"rightbar",
|
|
287
|
+
"input"
|
|
288
|
+
];
|
|
289
|
+
const DEFAULT_PART_BLURS = {
|
|
290
|
+
bg: 0,
|
|
291
|
+
sidebar: 0,
|
|
292
|
+
card: 0,
|
|
293
|
+
settings: 0,
|
|
294
|
+
chat: 0,
|
|
295
|
+
trajectory: 0,
|
|
296
|
+
rightbar: 0,
|
|
297
|
+
input: 0
|
|
298
|
+
};
|
|
299
|
+
/** A default config with independent nested objects (never hand out the shared ones). */
|
|
300
|
+
function freshThemeConfig() {
|
|
301
|
+
return {
|
|
302
|
+
rules: [],
|
|
303
|
+
opacities: { ...DEFAULT_PART_OPACITIES },
|
|
304
|
+
blurs: { ...DEFAULT_PART_BLURS },
|
|
305
|
+
settingsOpacity: 1,
|
|
306
|
+
chatTextOpacity: 0,
|
|
307
|
+
trajectoryOpacity: 1,
|
|
308
|
+
rightbarOpacity: null,
|
|
309
|
+
autoExtract: true
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/** Slot names reach the filesystem, so they are strictly whitelisted. */
|
|
313
|
+
const SLOT_RE = /^[A-Za-z0-9_-]{1,32}$/;
|
|
314
|
+
function clamp$1(n, lo, hi, def) {
|
|
315
|
+
return typeof n === "number" && isFinite(n) ? Math.min(hi, Math.max(lo, n)) : def;
|
|
316
|
+
}
|
|
317
|
+
const clamp01 = (n, def) => clamp$1(n, 0, 1, def);
|
|
318
|
+
function normalizeBgState(s) {
|
|
319
|
+
const v = s ?? {};
|
|
320
|
+
return {
|
|
321
|
+
zoom: clamp$1(v.zoom, .1, 10, 1),
|
|
322
|
+
x: typeof v.x === "number" && isFinite(v.x) ? v.x : 0,
|
|
323
|
+
y: typeof v.y === "number" && isFinite(v.y) ? v.y : 0,
|
|
324
|
+
iw: typeof v.iw === "number" && v.iw > 0 ? v.iw : 0,
|
|
325
|
+
ih: typeof v.ih === "number" && v.ih > 0 ? v.ih : 0
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
/** One `[h, s, l]` triple, or null when the value is not a complete finite triple. */
|
|
329
|
+
function normalizeHsl(raw) {
|
|
330
|
+
if (!Array.isArray(raw) || raw.length !== 3) return null;
|
|
331
|
+
if (!raw.every((n) => typeof n === "number" && isFinite(n))) return null;
|
|
332
|
+
return [
|
|
333
|
+
clamp$1(raw[0], 0, 360, 220),
|
|
334
|
+
clamp$1(raw[1], 0, 1, .55),
|
|
335
|
+
clamp$1(raw[2], 0, 1, .25)
|
|
336
|
+
];
|
|
337
|
+
}
|
|
338
|
+
/** Coerce one persisted rule, or null when it lacks a usable id/slot. */
|
|
339
|
+
function normalizeRule(raw) {
|
|
340
|
+
const r = raw ?? {};
|
|
341
|
+
const id = typeof r.id === "string" && r.id !== "" ? r.id : null;
|
|
342
|
+
const slot = typeof r.slot === "string" && SLOT_RE.test(r.slot) ? r.slot : null;
|
|
343
|
+
if (id === null || slot === null) return null;
|
|
344
|
+
const mode = BG_MODES$1.includes(r.bgMode) ? r.bgMode : "fit";
|
|
345
|
+
return {
|
|
346
|
+
id,
|
|
347
|
+
slot,
|
|
348
|
+
match: typeof r.match === "string" ? r.match : "",
|
|
349
|
+
enabled: r.enabled !== false,
|
|
350
|
+
color: normalizeHsl(r.color),
|
|
351
|
+
bgMode: mode,
|
|
352
|
+
wallpaperOpacity: clamp01(r.wallpaperOpacity, 1),
|
|
353
|
+
blur: clamp$1(r.blur, 0, 60, 0),
|
|
354
|
+
bgState: normalizeBgState(r.bgState)
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/** Coerce an unknown persisted value into a valid ThemeConfig, falling back per-field. */
|
|
358
|
+
function normalizeConfig(raw) {
|
|
359
|
+
const r = raw ?? {};
|
|
360
|
+
const rules = Array.isArray(r.rules) ? r.rules.map(normalizeRule).filter((x) => x !== null) : [];
|
|
361
|
+
const ops = r.opacities ?? {};
|
|
362
|
+
const bl = r.blurs ?? {};
|
|
363
|
+
const blurs = {};
|
|
364
|
+
for (const k of PART_BLUR_KEYS) blurs[k] = clamp$1(bl[k], 0, 60, DEFAULT_PART_BLURS[k]);
|
|
365
|
+
const opacities = {};
|
|
366
|
+
for (const k of PART_OPACITY_KEYS) opacities[k] = clamp01(ops[k], DEFAULT_PART_OPACITIES[k]);
|
|
367
|
+
return {
|
|
368
|
+
rules,
|
|
369
|
+
opacities,
|
|
370
|
+
blurs,
|
|
371
|
+
settingsOpacity: clamp01(r.settingsOpacity, 1),
|
|
372
|
+
chatTextOpacity: clamp01(r.chatTextOpacity, 0),
|
|
373
|
+
trajectoryOpacity: clamp01(r.trajectoryOpacity, 1),
|
|
374
|
+
rightbarOpacity: typeof r.rightbarOpacity === "number" && isFinite(r.rightbarOpacity) ? clamp01(r.rightbarOpacity, 1) : null,
|
|
375
|
+
autoExtract: r.autoExtract !== false
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
//#endregion
|
|
379
|
+
//#region src/client/state.ts
|
|
249
380
|
const PALETTE = [
|
|
250
381
|
[
|
|
251
382
|
356,
|
|
@@ -288,41 +419,8 @@ window.__ModuleLoader__.load({
|
|
|
288
419
|
.58
|
|
289
420
|
]
|
|
290
421
|
];
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
opacities: {
|
|
294
|
-
bg: .85,
|
|
295
|
-
sidebar: .93,
|
|
296
|
-
card: 1,
|
|
297
|
-
input: 1
|
|
298
|
-
},
|
|
299
|
-
blurs: {
|
|
300
|
-
bg: 0,
|
|
301
|
-
sidebar: 0,
|
|
302
|
-
card: 0,
|
|
303
|
-
settings: 0,
|
|
304
|
-
chat: 0,
|
|
305
|
-
trajectory: 0,
|
|
306
|
-
rightbar: 0,
|
|
307
|
-
input: 0
|
|
308
|
-
},
|
|
309
|
-
settingsOpacity: 1,
|
|
310
|
-
chatTextOpacity: 0,
|
|
311
|
-
trajectoryOpacity: 1,
|
|
312
|
-
rightbarOpacity: null
|
|
313
|
-
};
|
|
314
|
-
function freshConfig() {
|
|
315
|
-
return {
|
|
316
|
-
rules: [],
|
|
317
|
-
opacities: { ...DEFAULT_CONFIG.opacities },
|
|
318
|
-
blurs: { ...DEFAULT_CONFIG.blurs },
|
|
319
|
-
settingsOpacity: DEFAULT_CONFIG.settingsOpacity,
|
|
320
|
-
chatTextOpacity: DEFAULT_CONFIG.chatTextOpacity,
|
|
321
|
-
trajectoryOpacity: DEFAULT_CONFIG.trajectoryOpacity,
|
|
322
|
-
rightbarOpacity: DEFAULT_CONFIG.rightbarOpacity
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
let cfg = freshConfig();
|
|
422
|
+
freshThemeConfig();
|
|
423
|
+
let cfg = freshThemeConfig();
|
|
326
424
|
const images = /* @__PURE__ */ new Map();
|
|
327
425
|
const displayUrls = /* @__PURE__ */ new Map();
|
|
328
426
|
function revokeDisplay(slot) {
|
|
@@ -419,8 +517,6 @@ window.__ModuleLoader__.load({
|
|
|
419
517
|
}
|
|
420
518
|
return `r${Date.now()}`;
|
|
421
519
|
}
|
|
422
|
-
const clamp01 = (n, def) => typeof n === "number" && isFinite(n) ? Math.min(1, Math.max(0, n)) : def;
|
|
423
|
-
const clamp$1 = (n, lo, hi, def) => typeof n === "number" && isFinite(n) ? Math.min(hi, Math.max(lo, n)) : def;
|
|
424
520
|
function rHasColor() {
|
|
425
521
|
return activeRule()?.color !== null && activeRule() !== null;
|
|
426
522
|
}
|
|
@@ -451,108 +547,33 @@ window.__ModuleLoader__.load({
|
|
|
451
547
|
function rOps() {
|
|
452
548
|
const o = cfg.opacities ?? {};
|
|
453
549
|
const out = {};
|
|
454
|
-
for (const k of [
|
|
455
|
-
"bg",
|
|
456
|
-
"sidebar",
|
|
457
|
-
"card",
|
|
458
|
-
"input"
|
|
459
|
-
]) out[k] = clamp01(o[k], DEFAULT_CONFIG.opacities[k]);
|
|
550
|
+
for (const k of PART_OPACITY_KEYS) out[k] = clamp01(o[k], DEFAULT_PART_OPACITIES[k]);
|
|
460
551
|
return out;
|
|
461
552
|
}
|
|
462
553
|
function rBlurs() {
|
|
463
554
|
const b = cfg.blurs ?? {};
|
|
464
555
|
const out = {};
|
|
465
|
-
for (const k of [
|
|
466
|
-
"bg",
|
|
467
|
-
"sidebar",
|
|
468
|
-
"card",
|
|
469
|
-
"settings",
|
|
470
|
-
"chat",
|
|
471
|
-
"trajectory",
|
|
472
|
-
"rightbar",
|
|
473
|
-
"input"
|
|
474
|
-
]) out[k] = clamp$1(b[k], 0, 60, DEFAULT_CONFIG.blurs[k]);
|
|
556
|
+
for (const k of PART_BLUR_KEYS) out[k] = clamp$1(b[k], 0, 60, DEFAULT_PART_BLURS[k]);
|
|
475
557
|
return out;
|
|
476
558
|
}
|
|
477
559
|
function rSop() {
|
|
478
|
-
return clamp01(cfg.settingsOpacity,
|
|
560
|
+
return clamp01(cfg.settingsOpacity, 1);
|
|
479
561
|
}
|
|
480
562
|
function rChatTextOpacity() {
|
|
481
|
-
return clamp01(cfg.chatTextOpacity,
|
|
563
|
+
return clamp01(cfg.chatTextOpacity, 0);
|
|
482
564
|
}
|
|
483
565
|
function rTrajectoryOpacity() {
|
|
484
|
-
return clamp01(cfg.trajectoryOpacity,
|
|
566
|
+
return clamp01(cfg.trajectoryOpacity, 1);
|
|
485
567
|
}
|
|
486
568
|
/** Own opacity of the file-preview panel; while unowned it IS the main background's. */
|
|
487
569
|
function rRightbarOpacity() {
|
|
488
570
|
const own = cfg.rightbarOpacity;
|
|
489
571
|
return typeof own === "number" && isFinite(own) ? clamp01(own, 1) : rOps().bg;
|
|
490
572
|
}
|
|
491
|
-
function adoptBgState(s) {
|
|
492
|
-
return {
|
|
493
|
-
zoom: clamp$1(s.zoom, .1, 10, 1),
|
|
494
|
-
x: typeof s.x === "number" && isFinite(s.x) ? s.x : 0,
|
|
495
|
-
y: typeof s.y === "number" && isFinite(s.y) ? s.y : 0,
|
|
496
|
-
iw: typeof s.iw === "number" && s.iw > 0 ? s.iw : 0,
|
|
497
|
-
ih: typeof s.ih === "number" && s.ih > 0 ? s.ih : 0
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
/** Coerce one persisted rule, or null when it lacks a usable id/slot. */
|
|
501
|
-
function normalizeRule(raw) {
|
|
502
|
-
const r = raw ?? {};
|
|
503
|
-
const id = typeof r.id === "string" && r.id !== "" ? r.id : null;
|
|
504
|
-
const slot = typeof r.slot === "string" && /^[A-Za-z0-9_-]{1,32}$/.test(r.slot) ? r.slot : null;
|
|
505
|
-
if (id === null || slot === null) return null;
|
|
506
|
-
const c = r.color;
|
|
507
|
-
const color = Array.isArray(c) && c.length === 3 && c.every((n) => typeof n === "number" && isFinite(n)) ? [
|
|
508
|
-
clamp$1(c[0], 0, 360, 220),
|
|
509
|
-
clamp$1(c[1], 0, 1, .55),
|
|
510
|
-
clamp$1(c[2], 0, 1, .25)
|
|
511
|
-
] : null;
|
|
512
|
-
return {
|
|
513
|
-
id,
|
|
514
|
-
slot,
|
|
515
|
-
match: typeof r.match === "string" ? r.match : "",
|
|
516
|
-
enabled: r.enabled !== false,
|
|
517
|
-
color,
|
|
518
|
-
bgMode: BG_MODES$1.includes(r.bgMode) ? r.bgMode : "fit",
|
|
519
|
-
wallpaperOpacity: clamp01(r.wallpaperOpacity, 1),
|
|
520
|
-
blur: clamp$1(r.blur, 0, 60, 0),
|
|
521
|
-
bgState: adoptBgState(r.bgState ?? {})
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
573
|
/** Move a possibly-absent partial config into the shape the UI reads. */
|
|
525
574
|
function adoptConfig(raw) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const ops = c.opacities ?? {};
|
|
529
|
-
const bl = c.blurs ?? {};
|
|
530
|
-
const blurs = {};
|
|
531
|
-
for (const k of [
|
|
532
|
-
"bg",
|
|
533
|
-
"sidebar",
|
|
534
|
-
"card",
|
|
535
|
-
"settings",
|
|
536
|
-
"chat",
|
|
537
|
-
"trajectory",
|
|
538
|
-
"rightbar",
|
|
539
|
-
"input"
|
|
540
|
-
]) blurs[k] = clamp$1(bl[k], 0, 60, DEFAULT_CONFIG.blurs[k]);
|
|
541
|
-
cfg = {
|
|
542
|
-
rules,
|
|
543
|
-
opacities: {
|
|
544
|
-
bg: clamp01(ops.bg, DEFAULT_CONFIG.opacities.bg),
|
|
545
|
-
sidebar: clamp01(ops.sidebar, DEFAULT_CONFIG.opacities.sidebar),
|
|
546
|
-
card: clamp01(ops.card, DEFAULT_CONFIG.opacities.card),
|
|
547
|
-
input: clamp01(ops.input, DEFAULT_CONFIG.opacities.input)
|
|
548
|
-
},
|
|
549
|
-
blurs,
|
|
550
|
-
settingsOpacity: clamp01(c.settingsOpacity, DEFAULT_CONFIG.settingsOpacity),
|
|
551
|
-
chatTextOpacity: clamp01(c.chatTextOpacity, DEFAULT_CONFIG.chatTextOpacity),
|
|
552
|
-
trajectoryOpacity: clamp01(c.trajectoryOpacity, DEFAULT_CONFIG.trajectoryOpacity),
|
|
553
|
-
rightbarOpacity: typeof c.rightbarOpacity === "number" && isFinite(c.rightbarOpacity) ? clamp01(c.rightbarOpacity, 1) : null
|
|
554
|
-
};
|
|
555
|
-
if (activeRuleId !== null && !rules.some((r) => r.id === activeRuleId)) {
|
|
575
|
+
cfg = normalizeConfig(raw);
|
|
576
|
+
if (activeRuleId !== null && !cfg.rules.some((r) => r.id === activeRuleId)) {
|
|
556
577
|
activeRuleId = null;
|
|
557
578
|
activeMatched = false;
|
|
558
579
|
}
|
|
@@ -706,90 +727,95 @@ window.__ModuleLoader__.load({
|
|
|
706
727
|
const l = (d) => Math.max(0, Math.min(1, lit + d));
|
|
707
728
|
const hsl = (hh, ss, ll) => `hsl(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%)`;
|
|
708
729
|
const rgba = (hh, ss, ll, a) => `hsla(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%,${a})`;
|
|
709
|
-
if (dark)
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
"
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
730
|
+
if (dark) {
|
|
731
|
+
const menuFill = hsl(h(0), s(0), l(.08));
|
|
732
|
+
return {
|
|
733
|
+
colorScheme: "dark",
|
|
734
|
+
tokens: {
|
|
735
|
+
"--dsw-alias-bg-base": hsl(h(0), s(0), l(-.04)),
|
|
736
|
+
"--dsw-alias-bg-layer-1": hsl(h(0), s(0), l(.02)),
|
|
737
|
+
"--dsw-alias-bg-layer-2": hsl(h(0), s(0), l(.07)),
|
|
738
|
+
"--dsw-alias-bg-layer-3": hsl(h(0), s(-.05), l(.12)),
|
|
739
|
+
"--dsw-alias-bg-overlay": hsl(h(0), s(-.05), l(.12)),
|
|
740
|
+
"--dsw-alias-bg-module-platform": hsl(h(0), s(0), l(.05)),
|
|
741
|
+
"--dsw-alias-bg-multi-select": hsl(h(0), s(0), l(.1)),
|
|
742
|
+
"--dsw-alias-bg-skeleton": "rgba(255,255,255,0.08)",
|
|
743
|
+
"--dsw-alias-border-l1": rgba(h(0), s(-.1), l(.18), .12),
|
|
744
|
+
"--dsw-alias-border-l2": rgba(h(0), s(-.1), l(.22), .22),
|
|
745
|
+
"--dsw-alias-border-l3": "rgba(255,255,255,0.16)",
|
|
746
|
+
"--dsw-alias-border-l4": "rgba(255,255,255,0.2)",
|
|
747
|
+
"--dsw-alias-border-inverted": "rgba(255,255,255,0.06)",
|
|
748
|
+
"--dsw-alias-label-primary": hsl(0, 0, 1),
|
|
749
|
+
"--dsw-alias-label-secondary": "rgba(255,255,255,0.85)",
|
|
750
|
+
"--dsw-alias-label-tertiary": "rgba(255,255,255,0.7)",
|
|
751
|
+
"--dsw-alias-label-caption": "rgba(255,255,255,0.5)",
|
|
752
|
+
"--dsw-alias-label-dimmed": "rgba(255,255,255,0.35)",
|
|
753
|
+
"--dsw-alias-label-quaternary": "rgba(255,255,255,0.25)",
|
|
754
|
+
"--dsw-alias-label-primary-dimmed": "rgba(255,255,255,0.92)",
|
|
755
|
+
"--dsw-alias-label-primary-foreground": hsl(0, 0, 1),
|
|
756
|
+
"--dsw-alias-label-primary-inverted": hsl(h(0), s(.08), Math.min(l(.06), .16)),
|
|
757
|
+
"--dsw-alias-label-primary-bluish": hsl(0, 0, 1),
|
|
758
|
+
"--dsw-alias-brand-primary": hsl(h(0), s(.1), Math.max(l(.2), .5)),
|
|
759
|
+
"--dsw-alias-brand-text": l(.2) > .6 ? "#000" : "#fff",
|
|
760
|
+
"--dsw-alias-button-primary-fill": hsl(h(0), s(.1), Math.max(l(.2), .5)),
|
|
761
|
+
"--dsw-alias-button-primary-hover": hsl(h(0), s(.1), Math.max(l(.28), .58)),
|
|
762
|
+
"--dsw-alias-button-primary-dimmed": hsl(h(0), s(0), l(.07)),
|
|
763
|
+
"--dsw-alias-button-elevated-fill": hsl(h(0), s(0), l(.04)),
|
|
764
|
+
"--dsw-alias-button-floating-fill": hsl(h(0), s(0), l(.02)),
|
|
765
|
+
"--dsw-alias-button-floating-hover": hsl(h(0), s(0), l(.1)),
|
|
766
|
+
"--dsw-alias-button-tool-bar-fill": "rgba(255,255,255,0.08)",
|
|
767
|
+
"--dsw-alias-button-tool-bar-hover": "rgba(255,255,255,0.12)",
|
|
768
|
+
"--dsw-alias-button-ghost-active-fill": hsl(h(0), s(0), l(.06)),
|
|
769
|
+
"--dsw-alias-button-ghost-active-border": "rgba(255,255,255,0.16)",
|
|
770
|
+
"--dsw-alias-button-ghost-active-hover": hsl(h(0), s(0), l(.09)),
|
|
771
|
+
"--dsw-alias-button-info-fill": "#679efe",
|
|
772
|
+
"--dsw-alias-button-info-hover": "#4176e6",
|
|
773
|
+
"--dsw-alias-button-contrast-fill": hsl(0, 0, 1),
|
|
774
|
+
"--dsw-alias-interactive-bg-hover": rgba(h(0), s(0), Math.max(l(.15), .4), .12),
|
|
775
|
+
"--dsw-alias-interactive-bg-hover-solid": rgba(h(0), s(0), Math.max(l(.15), .4), .16),
|
|
776
|
+
"--dsw-alias-interactive-bg-hover-accent": "rgba(255,255,255,0.24)",
|
|
777
|
+
"--dsw-alias-interactive-bg-hover-danger": "rgba(242,90,90,0.15)",
|
|
778
|
+
"--dsw-alias-interactive-bg-active": rgba(h(0), s(0), Math.max(l(.15), .4), .2),
|
|
779
|
+
"--dsw-alias-markdown-code-block": hsl(h(0), s(0), l(-.06)),
|
|
780
|
+
"--dsw-alias-markdown-code-block-banner": hsl(h(0), s(0), l(-.02)),
|
|
781
|
+
"--dsw-alias-markdown-inline-code": hsl(h(0), s(0), l(.04)),
|
|
782
|
+
"--dsw-alias-markdown-placeholder": hsl(h(0), s(0), l(-.02)),
|
|
783
|
+
"--dsw-alias-markdown-tag": hsl(h(0), s(0), l(.05)),
|
|
784
|
+
"--dsw-alias-markdown-citation": hsl(h(0), s(0), l(.06)),
|
|
785
|
+
"--dsw-alias-markdown-code-segment-selected": hsl(h(0), s(0), l(.05)),
|
|
786
|
+
"--dsw-alias-markdown-code-segment-unselected": hsl(h(0), s(0), l(-.05)),
|
|
787
|
+
"--dsw-alias-state-error-primary": "#ff5c72",
|
|
788
|
+
"--dsw-alias-state-error-secondary": "#ff8aa0",
|
|
789
|
+
"--dsw-alias-state-success-primary": "#3ddc84",
|
|
790
|
+
"--dsw-alias-state-success-secondary": "#69eea4",
|
|
791
|
+
"--dsw-alias-state-success-tertiary": "#233c2c",
|
|
792
|
+
"--dsw-alias-state-warn-primary": "#ffb347",
|
|
793
|
+
"--dsw-alias-state-warn-secondary": "#ffc980",
|
|
794
|
+
"--dsw-alias-state-warn-tertiary": "#27241f",
|
|
795
|
+
"--dsw-alias-state-warn-label": "#dd8629",
|
|
796
|
+
"--dsw-alias-state-business-primary": "#679efe",
|
|
797
|
+
"--dsw-alias-state-business-tertiary": "#34415b",
|
|
798
|
+
"--dsw-specific-sidebar-fill": hsl(h(0), s(0), l(-.06)),
|
|
799
|
+
"--dsw-specific-sidebar-nav-item-active": hsl(h(0), s(0), l(.04)),
|
|
800
|
+
"--dsw-specific-sidebar-nav-item-hover": hsl(h(0), s(0), l(0)),
|
|
801
|
+
"--dsw-specific-input-major": hsl(h(0), s(0), l(.02)),
|
|
802
|
+
"--dsw-specific-menu": menuFill,
|
|
803
|
+
"--dsw-menu-surface-fill": menuFill,
|
|
804
|
+
"--dsw-specific-bubble": hsl(h(0), s(0), l(.03)),
|
|
805
|
+
"--dsw-specific-bubble-highlight": hsl(h(0), s(0), l(.08)),
|
|
806
|
+
"--dsw-specific-selector": hsl(h(0), s(0), l(.05)),
|
|
807
|
+
"--dsw-specific-login-input": hsl(h(0), s(0), l(.03)),
|
|
808
|
+
"--dsw-specific-tip": hsl(h(0), s(0), l(.05)),
|
|
809
|
+
"--dsw-alias-toast-bg": hsl(h(0), s(0), l(.08)),
|
|
810
|
+
"--dsw-alias-tooltip-bg": hsl(h(0), s(0), l(.08)),
|
|
811
|
+
"--dsw-alias-scrollbar-bg-l1": hsl(h(0), s(-.05), l(.12)),
|
|
812
|
+
"--dsw-alias-scrollbar-bg-l2": hsl(h(0), s(-.05), l(.16)),
|
|
813
|
+
"--dsw-alias-scrollbar-hover-l1": hsl(h(0), s(-.05), l(.22)),
|
|
814
|
+
"--dsw-alias-scrollbar-hover-l2": hsl(h(0), s(-.05), l(.22))
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
const menuFill = hsl(h(0), s(-.12), l(.15));
|
|
793
819
|
return {
|
|
794
820
|
colorScheme: "light",
|
|
795
821
|
tokens: {
|
|
@@ -820,7 +846,8 @@ window.__ModuleLoader__.load({
|
|
|
820
846
|
"--dsw-specific-sidebar-nav-item-active": hsl(h(0), s(-.08), l(.05)),
|
|
821
847
|
"--dsw-specific-sidebar-nav-item-hover": hsl(h(0), s(-.12), l(0)),
|
|
822
848
|
"--dsw-specific-input-major": hsl(h(0), s(-.12), l(.1)),
|
|
823
|
-
"--dsw-specific-menu":
|
|
849
|
+
"--dsw-specific-menu": menuFill,
|
|
850
|
+
"--dsw-menu-surface-fill": menuFill,
|
|
824
851
|
"--dsw-alias-scrollbar-bg-l1": hsl(h(0), s(-.1), l(-.08)),
|
|
825
852
|
"--dsw-alias-scrollbar-bg-l2": hsl(h(0), s(-.08), l(-.12)),
|
|
826
853
|
"--dsw-alias-scrollbar-hover-l1": hsl(h(0), s(-.08), l(-.16)),
|
|
@@ -909,7 +936,7 @@ window.__ModuleLoader__.load({
|
|
|
909
936
|
const max = Math.max(r, gg, b), min = Math.min(r, gg, b);
|
|
910
937
|
const v = max / 255;
|
|
911
938
|
const s = max === 0 ? 0 : (max - min) / max;
|
|
912
|
-
totalLum +=
|
|
939
|
+
totalLum += (.2126 * r + .7152 * gg + .0722 * b) / 255;
|
|
913
940
|
sampled++;
|
|
914
941
|
if (s < .08 || v < .12 || v > .97) continue;
|
|
915
942
|
const key = r >> 4 << 8 | gg >> 4 << 4 | b >> 4;
|
|
@@ -1059,7 +1086,8 @@ window.__ModuleLoader__.load({
|
|
|
1059
1086
|
"--dsw-alias-bg-layer-1",
|
|
1060
1087
|
"--dsw-alias-bg-layer-2",
|
|
1061
1088
|
"--dsw-alias-bg-layer-3",
|
|
1062
|
-
"--dsw-specific-menu"
|
|
1089
|
+
"--dsw-specific-menu",
|
|
1090
|
+
"--dsw-menu-surface-fill"
|
|
1063
1091
|
]
|
|
1064
1092
|
},
|
|
1065
1093
|
{
|
|
@@ -1074,7 +1102,8 @@ window.__ModuleLoader__.load({
|
|
|
1074
1102
|
"--dsw-alias-bg-layer-2": "--dsh-any-op-card-2",
|
|
1075
1103
|
"--dsw-alias-bg-layer-3": "--dsh-any-op-card-3",
|
|
1076
1104
|
"--dsw-specific-input-major": "--dsh-any-op-input",
|
|
1077
|
-
"--dsw-specific-menu": "--dsh-any-op-menu"
|
|
1105
|
+
"--dsw-specific-menu": "--dsh-any-op-menu",
|
|
1106
|
+
"--dsw-menu-surface-fill": "--dsh-any-op-menu"
|
|
1078
1107
|
};
|
|
1079
1108
|
let baseTokenKey = "";
|
|
1080
1109
|
let pendingOps = null;
|
|
@@ -1148,7 +1177,7 @@ window.__ModuleLoader__.load({
|
|
|
1148
1177
|
if (layer2 !== void 0) document.documentElement.style.setProperty("--dsh-any-traj-layer-2", toRgba(layer2, op));
|
|
1149
1178
|
if (layer3 !== void 0) document.documentElement.style.setProperty("--dsh-any-traj-layer-3", toRgba(layer3, op));
|
|
1150
1179
|
}
|
|
1151
|
-
const RIGHTBAR_STYLE_RULE = "div[data-sidebar-right-panel]{background:var(--dsh-any-bg-rightbar,var(--dsw-alias-bg-base))!important
|
|
1180
|
+
const RIGHTBAR_STYLE_RULE = "div[data-sidebar-right-panel]:not(:has([data-dockkit-content],[data-dockkit-empty]))[data-sidebar-right-open],div[data-sidebar-right-panel] [data-dockkit-content]:not([data-dockkit-float]),div[data-sidebar-right-panel] [data-dockkit-empty]{background:var(--dsh-any-bg-rightbar,var(--dsw-alias-bg-base))!important}div[data-sidebar-right-panel][data-sidebar-right-open]{-webkit-backdrop-filter:var(--dsh-any-blur-rightbar,none);backdrop-filter:var(--dsh-any-blur-rightbar,none)}";
|
|
1152
1181
|
/** Paint the file-preview panel's surface from its own slider. */
|
|
1153
1182
|
function applyRightbarOverrides(op) {
|
|
1154
1183
|
const root = document.documentElement;
|
|
@@ -1867,6 +1896,46 @@ window.__ModuleLoader__.load({
|
|
|
1867
1896
|
model
|
|
1868
1897
|
};
|
|
1869
1898
|
}
|
|
1899
|
+
/** A non-empty string id, or null. */
|
|
1900
|
+
function asId(value) {
|
|
1901
|
+
return typeof value === "string" && value !== "" ? value : null;
|
|
1902
|
+
}
|
|
1903
|
+
/**
|
|
1904
|
+
* The id of the session the main view is showing.
|
|
1905
|
+
*
|
|
1906
|
+
* The model is read per session, so this hop has to answer before any of the
|
|
1907
|
+
* others can. 0.1.7 moved the answer: `sessions.list` stopped publishing a single
|
|
1908
|
+
* `current` id in favour of a row table (`ids` / `byId` / `phase`), and the main
|
|
1909
|
+
* view's session is now whatever holds a `mainView` retention — the same row the
|
|
1910
|
+
* host's own `uiSession.current` binding source is built from. Reading only
|
|
1911
|
+
* `list.current` therefore finds nothing on 0.1.7, and a plugin with no session
|
|
1912
|
+
* id can only ever fall back to rule 1: the background stops following the model.
|
|
1913
|
+
*
|
|
1914
|
+
* The hops are tried in order of authority and every one is optional, so this
|
|
1915
|
+
* answers on both host generations — and while `uiSession` is still mounting.
|
|
1916
|
+
*/
|
|
1917
|
+
function resolveMainSessionId(uiCurrent, snapshot) {
|
|
1918
|
+
const fromUiSession = asId(uiCurrent?.key);
|
|
1919
|
+
if (fromUiSession !== null) return fromUiSession;
|
|
1920
|
+
const legacy = asId(snapshot?.current);
|
|
1921
|
+
if (legacy !== null) return legacy;
|
|
1922
|
+
const byId = snapshot?.byId;
|
|
1923
|
+
if (byId !== void 0 && byId !== null) {
|
|
1924
|
+
for (const row of Object.values(byId)) if ((row?.retainedBy?.mainView ?? 0) > 0) {
|
|
1925
|
+
const id = asId(row?.id);
|
|
1926
|
+
if (id !== null) return id;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
return null;
|
|
1930
|
+
}
|
|
1931
|
+
/** Read `uiSession.current` (if that service is on this host) and resolve. */
|
|
1932
|
+
function mainSessionId(ctx, list) {
|
|
1933
|
+
let uiCurrent;
|
|
1934
|
+
try {
|
|
1935
|
+
uiCurrent = ctx.get("uiSession")?.current?.getSnapshot?.();
|
|
1936
|
+
} catch {}
|
|
1937
|
+
return resolveMainSessionId(uiCurrent, list?.getSnapshot());
|
|
1938
|
+
}
|
|
1870
1939
|
/**
|
|
1871
1940
|
* Watch the current session's model selection.
|
|
1872
1941
|
*
|
|
@@ -1925,7 +1994,7 @@ window.__ModuleLoader__.load({
|
|
|
1925
1994
|
};
|
|
1926
1995
|
const note = () => {
|
|
1927
1996
|
if (service === null) return "no-service";
|
|
1928
|
-
if (
|
|
1997
|
+
if (sessionId === null) return "no-session";
|
|
1929
1998
|
if (projected === null && directory === null) return "no-projection";
|
|
1930
1999
|
return "empty-selection";
|
|
1931
2000
|
};
|
|
@@ -1957,7 +2026,7 @@ window.__ModuleLoader__.load({
|
|
|
1957
2026
|
onChange(text, name !== "" ? name : model !== "" ? model : provider, "session", noteValue);
|
|
1958
2027
|
};
|
|
1959
2028
|
const bind = () => {
|
|
1960
|
-
const id = list
|
|
2029
|
+
const id = mainSessionId(ctx, list);
|
|
1961
2030
|
if (id === sessionId && (directory !== null || projected !== null)) {
|
|
1962
2031
|
emit(false);
|
|
1963
2032
|
return;
|
|
@@ -1990,7 +2059,7 @@ window.__ModuleLoader__.load({
|
|
|
1990
2059
|
};
|
|
1991
2060
|
const tick = () => {
|
|
1992
2061
|
if (list === null) return;
|
|
1993
|
-
if ((list
|
|
2062
|
+
if (mainSessionId(ctx, list) !== sessionId || directory === null && projected === null) bind();
|
|
1994
2063
|
else emit(false);
|
|
1995
2064
|
};
|
|
1996
2065
|
/**
|
|
@@ -2189,12 +2258,6 @@ window.__ModuleLoader__.load({
|
|
|
2189
2258
|
.dab-crash-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center;line-height:1.5}
|
|
2190
2259
|
|
|
2191
2260
|
/* ── model rules ─────────────────────────────────────────────────────────── */
|
|
2192
|
-
.dab-status{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:12.5px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
2193
|
-
.dab-status-model{font-family:var(--dab-mono);font-size:12.5px;font-weight:600;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border-radius:8px;padding:3px 9px}
|
|
2194
|
-
.dab-status-arrow{color:var(--dsw-alias-brand-primary);font-weight:700}
|
|
2195
|
-
.dab-status-hit{color:var(--dsw-alias-brand-primary);font-weight:600}
|
|
2196
|
-
.dab-status-none{color:var(--dsw-alias-state-error-primary)}
|
|
2197
|
-
.dab-status-src{font-size:11px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-tertiary));background:var(--dsw-alias-interactive-bg-hover);border-radius:6px;padding:2px 7px}
|
|
2198
2261
|
.dab-rules{display:flex;flex-direction:column;gap:12px}
|
|
2199
2262
|
.dab-rule{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:14px;transition:border-color .25s,box-shadow .25s,opacity .25s}
|
|
2200
2263
|
.dab-rule.is-active{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 16%,transparent)}
|
|
@@ -2698,11 +2761,6 @@ window.__ModuleLoader__.load({
|
|
|
2698
2761
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2699
2762
|
className: "dab-desc",
|
|
2700
2763
|
children: t("descInterface")
|
|
2701
|
-
}),
|
|
2702
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2703
|
-
className: "dab-hint",
|
|
2704
|
-
style: { marginTop: 7 },
|
|
2705
|
-
children: t("uiScopeHint")
|
|
2706
2764
|
})
|
|
2707
2765
|
]
|
|
2708
2766
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -2800,12 +2858,7 @@ window.__ModuleLoader__.load({
|
|
|
2800
2858
|
blurs[blurKey] = v;
|
|
2801
2859
|
setBlurs(blurs);
|
|
2802
2860
|
}
|
|
2803
|
-
})
|
|
2804
|
-
isRightbar ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2805
|
-
className: "dab-hint",
|
|
2806
|
-
style: { marginTop: 9 },
|
|
2807
|
-
children: t("uiPreviewHint")
|
|
2808
|
-
}) : null
|
|
2861
|
+
})
|
|
2809
2862
|
]
|
|
2810
2863
|
}, blurKey);
|
|
2811
2864
|
})
|
|
@@ -3590,7 +3643,20 @@ window.__ModuleLoader__.load({
|
|
|
3590
3643
|
const { t, useStore } = p;
|
|
3591
3644
|
const store = useStore((s) => s);
|
|
3592
3645
|
const rules = cfg.rules;
|
|
3593
|
-
const
|
|
3646
|
+
const [text, setText] = (0, react.useState)("");
|
|
3647
|
+
const [touched, setTouched] = (0, react.useState)(false);
|
|
3648
|
+
(0, react.useEffect)(() => {
|
|
3649
|
+
if (!touched) setText(store.model);
|
|
3650
|
+
}, [store.model, touched]);
|
|
3651
|
+
const probe = text.trim();
|
|
3652
|
+
const result = (() => {
|
|
3653
|
+
if (probe === "") return null;
|
|
3654
|
+
const hit = matchRule(rules, probe);
|
|
3655
|
+
const rule = hit.rule;
|
|
3656
|
+
if (rule === null) return null;
|
|
3657
|
+
const n = rules.findIndex((r) => r.id === rule.id) + 1;
|
|
3658
|
+
return `${hit.matched ? t("tryoutHit") : t("tryoutFallback")} ${n}`;
|
|
3659
|
+
})();
|
|
3594
3660
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3595
3661
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
3596
3662
|
className: "dab-head dab-rise",
|
|
@@ -3614,48 +3680,50 @@ window.__ModuleLoader__.load({
|
|
|
3614
3680
|
className: "dab-card dab-rise",
|
|
3615
3681
|
style: { "--d": 1 },
|
|
3616
3682
|
children: [
|
|
3683
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3684
|
+
className: "dab-swatch-title",
|
|
3685
|
+
children: t("tryoutTitle")
|
|
3686
|
+
}),
|
|
3617
3687
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
activeIndex + 1
|
|
3644
|
-
]
|
|
3645
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3646
|
-
className: "dab-status-none",
|
|
3647
|
-
children: t("statusNone")
|
|
3648
|
-
})
|
|
3649
|
-
]
|
|
3688
|
+
style: {
|
|
3689
|
+
marginTop: 10,
|
|
3690
|
+
display: "flex",
|
|
3691
|
+
flexWrap: "wrap",
|
|
3692
|
+
gap: 8,
|
|
3693
|
+
alignItems: "center"
|
|
3694
|
+
},
|
|
3695
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3696
|
+
type: "text",
|
|
3697
|
+
className: "dab-urlinput",
|
|
3698
|
+
value: text,
|
|
3699
|
+
placeholder: t("tryoutPlaceholder"),
|
|
3700
|
+
onChange: (e) => {
|
|
3701
|
+
setTouched(true);
|
|
3702
|
+
setText(e.target.value);
|
|
3703
|
+
}
|
|
3704
|
+
}), store.model !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3705
|
+
type: "button",
|
|
3706
|
+
className: "dab-btn",
|
|
3707
|
+
onClick: () => {
|
|
3708
|
+
setTouched(true);
|
|
3709
|
+
setText(store.model);
|
|
3710
|
+
},
|
|
3711
|
+
children: t("tryoutUseCurrent")
|
|
3712
|
+
}) : null]
|
|
3650
3713
|
}),
|
|
3651
|
-
|
|
3714
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3652
3715
|
className: "dab-hint",
|
|
3653
3716
|
style: { marginTop: 9 },
|
|
3717
|
+
children: probe === "" ? t("tryoutEmpty") : result === null ? t("tryoutNone") : result
|
|
3718
|
+
}),
|
|
3719
|
+
store.model === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3720
|
+
className: "dab-hint",
|
|
3721
|
+
style: { marginTop: 6 },
|
|
3654
3722
|
children: t("statusUnknownHint")
|
|
3655
3723
|
}) : null,
|
|
3656
3724
|
store.model !== "" && store.modelSource === "default" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3657
3725
|
className: "dab-hint",
|
|
3658
|
-
style: { marginTop:
|
|
3726
|
+
style: { marginTop: 6 },
|
|
3659
3727
|
children: t("statusSourceDefaultHint")
|
|
3660
3728
|
}) : null,
|
|
3661
3729
|
MODEL_NOTE_KEYS[store.modelNote] !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -3678,6 +3746,30 @@ window.__ModuleLoader__.load({
|
|
|
3678
3746
|
style: { marginBottom: 11 },
|
|
3679
3747
|
children: t("rulesHint")
|
|
3680
3748
|
}),
|
|
3749
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3750
|
+
className: "dab-chip-row",
|
|
3751
|
+
style: {
|
|
3752
|
+
marginBottom: 12,
|
|
3753
|
+
alignItems: "center"
|
|
3754
|
+
},
|
|
3755
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3756
|
+
type: "button",
|
|
3757
|
+
className: `dab-toggle${cfg.autoExtract ? " is-on" : ""}`,
|
|
3758
|
+
role: "switch",
|
|
3759
|
+
"aria-checked": cfg.autoExtract,
|
|
3760
|
+
title: t("autoExtract"),
|
|
3761
|
+
onClick: () => p.setAutoExtract(!cfg.autoExtract),
|
|
3762
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dab-toggle-knob" })
|
|
3763
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3764
|
+
className: "dab-hint",
|
|
3765
|
+
children: t("autoExtract")
|
|
3766
|
+
})]
|
|
3767
|
+
}),
|
|
3768
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3769
|
+
className: "dab-hint",
|
|
3770
|
+
style: { marginBottom: 11 },
|
|
3771
|
+
children: t("autoExtractHint")
|
|
3772
|
+
}),
|
|
3681
3773
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3682
3774
|
className: "dab-rules",
|
|
3683
3775
|
children: rules.map((rule, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuleCard, {
|
|
@@ -4498,6 +4590,36 @@ window.__ModuleLoader__.load({
|
|
|
4498
4590
|
zh,
|
|
4499
4591
|
en
|
|
4500
4592
|
}), "dsh-background-by-model: i18n");
|
|
4593
|
+
/**
|
|
4594
|
+
* The automatic half of "extract from image": fill a rule's theme color from
|
|
4595
|
+
* the picture it just received, but only while the rule has no color at all —
|
|
4596
|
+
* a color the user picked (or a previous extraction produced) is never
|
|
4597
|
+
* overwritten, so this cannot fight a deliberate choice.
|
|
4598
|
+
*
|
|
4599
|
+
* The decode is asynchronous, so the "still empty?" question is asked AGAIN on
|
|
4600
|
+
* arrival: a color chosen while it ran must win over the one being computed.
|
|
4601
|
+
*/
|
|
4602
|
+
const maybeAutoExtract = async (id) => {
|
|
4603
|
+
if (!cfg.autoExtract) return;
|
|
4604
|
+
const rule = ruleById(id);
|
|
4605
|
+
if (rule === null || rule.color !== null) return;
|
|
4606
|
+
const url = displayImageOf(rule.slot);
|
|
4607
|
+
if (url === null) return;
|
|
4608
|
+
let hsl = null;
|
|
4609
|
+
try {
|
|
4610
|
+
hsl = await extractWallpaperColor(url, rule.bgState);
|
|
4611
|
+
} catch {
|
|
4612
|
+
hsl = null;
|
|
4613
|
+
}
|
|
4614
|
+
if (hsl === null) return;
|
|
4615
|
+
const current = ruleById(id);
|
|
4616
|
+
if (current === null || current.color !== null) return;
|
|
4617
|
+
current.color = hsl;
|
|
4618
|
+
rulesRev++;
|
|
4619
|
+
saveConfig();
|
|
4620
|
+
if (id === activeRuleId) applyActive();
|
|
4621
|
+
else sync();
|
|
4622
|
+
};
|
|
4501
4623
|
const sectionInject = (actions) => {
|
|
4502
4624
|
bound = actions;
|
|
4503
4625
|
sync();
|
|
@@ -4552,6 +4674,7 @@ window.__ModuleLoader__.load({
|
|
|
4552
4674
|
dataUrl === null ? deleteImage(rule.slot) : writeImage(rule.slot, dataUrl);
|
|
4553
4675
|
if (id === activeRuleId) applyActive();
|
|
4554
4676
|
else sync();
|
|
4677
|
+
if (dataUrl !== null) maybeAutoExtract(id);
|
|
4555
4678
|
},
|
|
4556
4679
|
setRuleImageFromUrl: async (id, url) => {
|
|
4557
4680
|
const rule = ruleById(id);
|
|
@@ -4564,6 +4687,7 @@ window.__ModuleLoader__.load({
|
|
|
4564
4687
|
setImage(rule.slot, res.dataUrl ?? null);
|
|
4565
4688
|
if (id === activeRuleId) applyActive();
|
|
4566
4689
|
else sync();
|
|
4690
|
+
maybeAutoExtract(id);
|
|
4567
4691
|
}
|
|
4568
4692
|
return res;
|
|
4569
4693
|
},
|
|
@@ -4603,6 +4727,11 @@ window.__ModuleLoader__.load({
|
|
|
4603
4727
|
applyRightbarOverrides(rRightbarOpacity());
|
|
4604
4728
|
saveConfig();
|
|
4605
4729
|
},
|
|
4730
|
+
setAutoExtract: (v) => {
|
|
4731
|
+
cfg.autoExtract = v;
|
|
4732
|
+
saveConfig();
|
|
4733
|
+
sync();
|
|
4734
|
+
},
|
|
4606
4735
|
exportTheme: () => {
|
|
4607
4736
|
const images = {};
|
|
4608
4737
|
for (const rule of cfg.rules) {
|