dsh-background-by-model 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -0
- package/CHANGELOG.zh.md +98 -0
- package/README.md +24 -93
- package/README.zh.md +24 -93
- package/lib/client.js +366 -106
- package/lib/client.js.map +1 -1
- package/package.json +4 -2
package/lib/client.js
CHANGED
|
@@ -78,7 +78,9 @@ window.__ModuleLoader__.load({
|
|
|
78
78
|
ruleEmptyHint: "这条规则还没有图片,不会被匹配到,也不会作为兜底",
|
|
79
79
|
ruleColor: "主题色",
|
|
80
80
|
ruleColorNone: "系统主题",
|
|
81
|
-
ruleColorNoneHint: "
|
|
81
|
+
ruleColorNoneHint: "未设颜色时跟随系统主题:界面用宿主的配色,壁纸与各部位的透明度、模糊照旧生效",
|
|
82
|
+
ruleColorPick: "自定义颜色",
|
|
83
|
+
ruleColorPickHint: "优先从本图取色,取不到就用默认色",
|
|
82
84
|
ruleColorExtract: "从本图提取",
|
|
83
85
|
ruleLayout: "布局模式",
|
|
84
86
|
ruleFraming: "取景",
|
|
@@ -183,7 +185,9 @@ window.__ModuleLoader__.load({
|
|
|
183
185
|
ruleEmptyHint: "This rule has no image — it can neither match nor serve as the fallback",
|
|
184
186
|
ruleColor: "Theme color",
|
|
185
187
|
ruleColorNone: "System theme",
|
|
186
|
-
ruleColorNoneHint: "Without a color this rule follows the system theme",
|
|
188
|
+
ruleColorNoneHint: "Without a color this rule follows the system theme: the host palette paints the interface while the wallpaper and every opacity/blur slider keep working",
|
|
189
|
+
ruleColorPick: "Custom color",
|
|
190
|
+
ruleColorPickHint: "Extracts from this image when it can, otherwise uses a default color",
|
|
187
191
|
ruleColorExtract: "Extract from image",
|
|
188
192
|
ruleLayout: "Layout mode",
|
|
189
193
|
ruleFraming: "Framing",
|
|
@@ -727,6 +731,7 @@ window.__ModuleLoader__.load({
|
|
|
727
731
|
const l = (d) => Math.max(0, Math.min(1, lit + d));
|
|
728
732
|
const hsl = (hh, ss, ll) => `hsl(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%)`;
|
|
729
733
|
const rgba = (hh, ss, ll, a) => `hsla(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%,${a})`;
|
|
734
|
+
const onBrand = l(.2) > .6 ? "#000" : "#fff";
|
|
730
735
|
if (dark) {
|
|
731
736
|
const menuFill = hsl(h(0), s(0), l(.08));
|
|
732
737
|
return {
|
|
@@ -752,11 +757,11 @@ window.__ModuleLoader__.load({
|
|
|
752
757
|
"--dsw-alias-label-dimmed": "rgba(255,255,255,0.35)",
|
|
753
758
|
"--dsw-alias-label-quaternary": "rgba(255,255,255,0.25)",
|
|
754
759
|
"--dsw-alias-label-primary-dimmed": "rgba(255,255,255,0.92)",
|
|
755
|
-
"--dsw-alias-label-primary-foreground":
|
|
760
|
+
"--dsw-alias-label-primary-foreground": onBrand,
|
|
756
761
|
"--dsw-alias-label-primary-inverted": hsl(h(0), s(.08), Math.min(l(.06), .16)),
|
|
757
762
|
"--dsw-alias-label-primary-bluish": hsl(0, 0, 1),
|
|
758
763
|
"--dsw-alias-brand-primary": hsl(h(0), s(.1), Math.max(l(.2), .5)),
|
|
759
|
-
"--dsw-alias-brand-text":
|
|
764
|
+
"--dsw-alias-brand-text": onBrand,
|
|
760
765
|
"--dsw-alias-button-primary-fill": hsl(h(0), s(.1), Math.max(l(.2), .5)),
|
|
761
766
|
"--dsw-alias-button-primary-hover": hsl(h(0), s(.1), Math.max(l(.28), .58)),
|
|
762
767
|
"--dsw-alias-button-primary-dimmed": hsl(h(0), s(0), l(.07)),
|
|
@@ -832,6 +837,7 @@ window.__ModuleLoader__.load({
|
|
|
832
837
|
"--dsw-alias-label-caption": "rgba(0,0,0,0.5)",
|
|
833
838
|
"--dsw-alias-label-dimmed": "rgba(0,0,0,0.35)",
|
|
834
839
|
"--dsw-alias-label-quaternary": "rgba(0,0,0,0.25)",
|
|
840
|
+
"--dsw-alias-label-primary-inverted": "#fff",
|
|
835
841
|
"--dsw-alias-brand-primary": hsl(h(0), s(.05), Math.min(l(-.18), .45)),
|
|
836
842
|
"--dsw-alias-brand-text": "#fff",
|
|
837
843
|
"--dsw-alias-button-primary-hover": hsl(h(0), s(.05), Math.min(l(-.12), .5)),
|
|
@@ -1067,7 +1073,7 @@ window.__ModuleLoader__.load({
|
|
|
1067
1073
|
.dab-shell{display:grid;grid-template-columns:158px minmax(0,1fr);gap:26px;align-items:start;padding-bottom:8px;width:100%;max-width:980px;margin:0 auto}
|
|
1068
1074
|
.dab-nav{position:sticky;top:0;display:flex;flex-direction:column;gap:18px}
|
|
1069
1075
|
.dab-brand{display:flex;align-items:center;gap:10px;padding:2px 6px}
|
|
1070
|
-
.dab-brand-tile{width:30px;height:30px;flex:none;border-radius:9px;display:grid;place-items:center;color:var(--dsw-alias-
|
|
1076
|
+
.dab-brand-tile{width:30px;height:30px;flex:none;border-radius:9px;display:grid;place-items:center;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-brand-primary);box-shadow:0 4px 14px -4px var(--dsw-alias-brand-primary)}
|
|
1071
1077
|
.dab-brand-name{font-size:13px;font-weight:650;letter-spacing:.01em;line-height:1.25}
|
|
1072
1078
|
.dab-brand-tag{font-size:9px;letter-spacing:.16em;font-weight:600;color:var(--dsw-alias-label-quaternary,var(--dsw-alias-label-tertiary));text-transform:uppercase}
|
|
1073
1079
|
.dab-nav-list{position:relative;display:flex;flex-direction:column;gap:4px}
|
|
@@ -1127,11 +1133,23 @@ window.__ModuleLoader__.load({
|
|
|
1127
1133
|
.dab-swatch-lg:hover{transform:scale(1.02)}
|
|
1128
1134
|
|
|
1129
1135
|
/* ── buttons & chips ─────────────────────────────────────────────────────── */
|
|
1136
|
+
/* Text/icon painted ON --dsw-alias-brand-primary reads
|
|
1137
|
+
* --dsw-alias-label-primary-inverted, never --dsw-alias-brand-text. The host's
|
|
1138
|
+
* brand-primary is a CONTRAST ink, not a hue: black in its light scheme and
|
|
1139
|
+
* near-white (#f9fafb) in its dark one, with brand-text equal to it in BOTH
|
|
1140
|
+
* (and unused by the host's own CSS). Following the system theme therefore made
|
|
1141
|
+
* every brand-filled control a filled box with an invisible label — a white
|
|
1142
|
+
* primary button and a white active chip on a dark dialog. It was only ever
|
|
1143
|
+
* readable while the plugin owned the palette and generated its own brand pair.
|
|
1144
|
+
* label-primary-inverted is the host's answer for ink on a brand/contrast fill
|
|
1145
|
+
* (its sidebar build badge paints exactly this pair) and it flips with the
|
|
1146
|
+
* scheme: #fff on the light scheme's black fill, #353638 on the dark scheme's
|
|
1147
|
+
* white one. */
|
|
1130
1148
|
.dab-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:34px;padding:0 14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:550;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease,opacity .18s ease,background .18s ease}
|
|
1131
1149
|
.dab-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 14px -6px rgba(0,0,0,.32)}
|
|
1132
1150
|
.dab-btn:active:not(:disabled){transform:translateY(0) scale(.97);box-shadow:none}
|
|
1133
1151
|
.dab-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
1134
|
-
.dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-
|
|
1152
|
+
.dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted);border-color:transparent}
|
|
1135
1153
|
.dab-btn-danger{color:var(--dsw-alias-state-error-primary)}
|
|
1136
1154
|
.dab-btn-ghost{background:transparent;border-color:transparent;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
1137
1155
|
.dab-btn-ghost:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);box-shadow:none}
|
|
@@ -1139,7 +1157,7 @@ window.__ModuleLoader__.load({
|
|
|
1139
1157
|
.dab-chip-row{display:flex;flex-wrap:wrap;gap:8px}
|
|
1140
1158
|
.dab-chip{height:30px;padding:0 14px;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary));font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:all .22s ease}
|
|
1141
1159
|
.dab-chip:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary)}
|
|
1142
|
-
.dab-chip.is-active{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-
|
|
1160
|
+
.dab-chip.is-active{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted);border-color:transparent}
|
|
1143
1161
|
|
|
1144
1162
|
/* ── sliders ─────────────────────────────────────────────────────────────── */
|
|
1145
1163
|
.dab-slider-block{display:flex;flex-direction:column;gap:6px}
|
|
@@ -1170,7 +1188,7 @@ window.__ModuleLoader__.load({
|
|
|
1170
1188
|
.dab-toggle{position:relative;width:42px;height:24px;flex:none;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;padding:0;transition:background .28s ease,border-color .28s ease}
|
|
1171
1189
|
.dab-toggle-knob{position:absolute;top:2.5px;left:2.5px;width:17px;height:17px;border-radius:50%;background:var(--dsw-alias-label-secondary,#999);box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .28s cubic-bezier(.22,1,.36,1),background .28s ease}
|
|
1172
1190
|
.dab-toggle.is-on{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
1173
|
-
.dab-toggle.is-on .dab-toggle-knob{transform:translateX(18px);background
|
|
1191
|
+
.dab-toggle.is-on .dab-toggle-knob{transform:translateX(18px);background:var(--dsw-alias-label-primary-inverted)}
|
|
1174
1192
|
|
|
1175
1193
|
/* ── background preview hero ─────────────────────────────────────────────── */
|
|
1176
1194
|
.dab-hero{position:relative;border-radius:16px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2)}
|
|
@@ -1208,7 +1226,7 @@ window.__ModuleLoader__.load({
|
|
|
1208
1226
|
.dab-overlay-hint{color:rgba(255,255,255,.62);font-size:12px}
|
|
1209
1227
|
.dab-modal-card{animation:dab-zoom-in .3s cubic-bezier(.22,1,.36,1) both;max-width:calc(100vw - 40px);max-height:calc(100vh - 120px);overflow:auto}
|
|
1210
1228
|
.dab-overlay .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent}
|
|
1211
|
-
.dab-overlay .dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-
|
|
1229
|
+
.dab-overlay .dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted)}
|
|
1212
1230
|
.dab-crash{display:flex;flex-direction:column;gap:10px;align-items:center;padding:28px 18px;border:1px solid var(--dsw-alias-border-l2);border-radius:16px}
|
|
1213
1231
|
.dab-crash-title{font-size:15px;font-weight:650}
|
|
1214
1232
|
.dab-crash-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center;line-height:1.5}
|
|
@@ -1341,6 +1359,24 @@ window.__ModuleLoader__.load({
|
|
|
1341
1359
|
}
|
|
1342
1360
|
//#endregion
|
|
1343
1361
|
//#region src/client/wallpaper.ts
|
|
1362
|
+
/**
|
|
1363
|
+
* `data-ds-dark-theme` value the plugin writes while it forces its own dark
|
|
1364
|
+
* palette. The host treats the attribute as a boolean (`toggleAttribute`), so a
|
|
1365
|
+
* plugin-specific value still matches every `body[data-ds-dark-theme]` rule
|
|
1366
|
+
* while staying distinguishable from the host's own write — which is what lets
|
|
1367
|
+
* `releaseOwnScheme` hand the flag back without clobbering the host's scheme.
|
|
1368
|
+
*/
|
|
1369
|
+
const OWN_SCHEME = "dsh-background-by-model";
|
|
1370
|
+
const DARK_ATTR = "data-ds-dark-theme";
|
|
1371
|
+
/**
|
|
1372
|
+
* Marker on <html> while the plugin owns a palette. The dialog/trajectory rules
|
|
1373
|
+
* below redirect NO-fallback tokens (`--dsw-alias-bg-layer-*`) to plugin-owned
|
|
1374
|
+
* variables, so they may only match while those variables are actually written:
|
|
1375
|
+
* without the gate a palette-less state would leave them reading a
|
|
1376
|
+
* guaranteed-invalid value (transparent panels) instead of handing the surface
|
|
1377
|
+
* back to the host untouched.
|
|
1378
|
+
*/
|
|
1379
|
+
const THEMED_ATTR = "data-dab-themed";
|
|
1344
1380
|
let wpEl = null;
|
|
1345
1381
|
let appliedTokenNames = [];
|
|
1346
1382
|
let tokenStyleEl = null;
|
|
@@ -1356,6 +1392,22 @@ window.__ModuleLoader__.load({
|
|
|
1356
1392
|
if (tokenStyleEl) tokenStyleEl.textContent = "";
|
|
1357
1393
|
for (const name of appliedTokenNames) document.body.style.removeProperty(name);
|
|
1358
1394
|
appliedTokenNames = [];
|
|
1395
|
+
baseTokenKey = "";
|
|
1396
|
+
lastBgKey = "";
|
|
1397
|
+
}
|
|
1398
|
+
/** Drop every surface the plugin owns: the variables the scoped
|
|
1399
|
+
* dialog/trajectory rules read, and the inline backgrounds written onto the
|
|
1400
|
+
* AppFrame columns. Used when no palette is available and at teardown — without
|
|
1401
|
+
* it the last color's surfaces outlive the color that produced them. */
|
|
1402
|
+
function clearOwnedSurfaces() {
|
|
1403
|
+
discoverParts();
|
|
1404
|
+
const root = document.documentElement;
|
|
1405
|
+
for (const name of OWNED_SURFACE_VARS) root.style.removeProperty(name);
|
|
1406
|
+
for (const el of [
|
|
1407
|
+
frameEl,
|
|
1408
|
+
centerEl,
|
|
1409
|
+
detailsEl
|
|
1410
|
+
]) el?.style.removeProperty("background");
|
|
1359
1411
|
}
|
|
1360
1412
|
const OPACITY_TOKEN_GROUPS = [
|
|
1361
1413
|
{
|
|
@@ -1392,6 +1444,142 @@ window.__ModuleLoader__.load({
|
|
|
1392
1444
|
"--dsw-menu-surface-fill": "--dsh-any-op-menu"
|
|
1393
1445
|
};
|
|
1394
1446
|
let baseTokenKey = "";
|
|
1447
|
+
const HOST_SURFACE_TOKENS = Object.keys(OPACITY_VARS);
|
|
1448
|
+
/** Plugin-owned variables the scoped dialog/trajectory rules read. */
|
|
1449
|
+
const SETTINGS_SURFACE_VARS = [
|
|
1450
|
+
"--dsh-any-bg-settings-surface",
|
|
1451
|
+
"--dsh-any-bg-settings-layer-1",
|
|
1452
|
+
"--dsh-any-bg-settings-layer-2",
|
|
1453
|
+
"--dsh-any-bg-settings-layer-3"
|
|
1454
|
+
];
|
|
1455
|
+
const TRAJECTORY_SURFACE_VARS = [
|
|
1456
|
+
"--dsh-any-traj-layer-1",
|
|
1457
|
+
"--dsh-any-traj-layer-2",
|
|
1458
|
+
"--dsh-any-traj-layer-3"
|
|
1459
|
+
];
|
|
1460
|
+
const OWNED_SURFACE_VARS = [...SETTINGS_SURFACE_VARS, ...TRAJECTORY_SURFACE_VARS];
|
|
1461
|
+
let hostProbe = null;
|
|
1462
|
+
/** Resolve any color the engine understands (hex, rgb()/hsl(), a var() chain,
|
|
1463
|
+
* color-mix(), …) to its USED value: only a used color can be re-emitted with
|
|
1464
|
+
* an alpha. Returns null when the engine rejects the value. */
|
|
1465
|
+
function resolveCssColor(raw) {
|
|
1466
|
+
const value = raw.trim();
|
|
1467
|
+
if (value === "") return null;
|
|
1468
|
+
if (hostProbe === null) {
|
|
1469
|
+
hostProbe = document.createElement("span");
|
|
1470
|
+
hostProbe.setAttribute("aria-hidden", "true");
|
|
1471
|
+
hostProbe.style.cssText = "position:absolute;width:0;height:0;pointer-events:none";
|
|
1472
|
+
}
|
|
1473
|
+
if (!hostProbe.isConnected) document.body.appendChild(hostProbe);
|
|
1474
|
+
hostProbe.style.color = "";
|
|
1475
|
+
hostProbe.style.color = value;
|
|
1476
|
+
if (hostProbe.style.color === "") return null;
|
|
1477
|
+
return getComputedStyle(hostProbe).color || null;
|
|
1478
|
+
}
|
|
1479
|
+
/** Read the host's own surface colors out of the live cascade. */
|
|
1480
|
+
function readHostPalette() {
|
|
1481
|
+
const sheet = tokenStyleEl;
|
|
1482
|
+
const muted = sheet !== null && sheet.isConnected && !sheet.disabled;
|
|
1483
|
+
if (muted) sheet.disabled = true;
|
|
1484
|
+
try {
|
|
1485
|
+
const computed = getComputedStyle(document.body);
|
|
1486
|
+
const tokens = {};
|
|
1487
|
+
for (const name of HOST_SURFACE_TOKENS) {
|
|
1488
|
+
const used = resolveCssColor(computed.getPropertyValue(name));
|
|
1489
|
+
if (used !== null) tokens[name] = used;
|
|
1490
|
+
}
|
|
1491
|
+
return tokens["--dsw-alias-bg-base"] === void 0 ? null : {
|
|
1492
|
+
own: false,
|
|
1493
|
+
tokens
|
|
1494
|
+
};
|
|
1495
|
+
} finally {
|
|
1496
|
+
if (muted) sheet.disabled = false;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
let hostPaletteCache = null;
|
|
1500
|
+
const HOST_PALETTE_TTL_MS = 1e3;
|
|
1501
|
+
function invalidateHostPalette() {
|
|
1502
|
+
hostPaletteCache = null;
|
|
1503
|
+
}
|
|
1504
|
+
function hostPalette() {
|
|
1505
|
+
const now = Date.now();
|
|
1506
|
+
if (hostPaletteCache !== null && now - hostPaletteCache.at < HOST_PALETTE_TTL_MS) return hostPaletteCache.palette;
|
|
1507
|
+
const read = readHostPalette();
|
|
1508
|
+
hostPaletteCache = {
|
|
1509
|
+
at: now,
|
|
1510
|
+
palette: read
|
|
1511
|
+
};
|
|
1512
|
+
return read;
|
|
1513
|
+
}
|
|
1514
|
+
/** The palette every surface is currently painted from. */
|
|
1515
|
+
function palette() {
|
|
1516
|
+
if (!rHasColor()) return hostPalette();
|
|
1517
|
+
const [h, s, l] = rColor();
|
|
1518
|
+
return {
|
|
1519
|
+
own: true,
|
|
1520
|
+
tokens: genTokens(h, s, l).tokens
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
/** A resolved color with a new alpha. The plugin's own tokens are `hsl()` and
|
|
1524
|
+
* the host's alias tokens resolve to hex, both of which `toRgba` parses; a host
|
|
1525
|
+
* publishing an already-composited value (`color(…)`, `oklab(…)`, …) cannot be
|
|
1526
|
+
* parsed there, and emitting it unchanged would paint an OPAQUE surface — the
|
|
1527
|
+
* one outcome the transparent-surface design must never fall back to. Those go
|
|
1528
|
+
* through `color-mix` instead. */
|
|
1529
|
+
function withAlpha(color, alpha) {
|
|
1530
|
+
const converted = toRgba(color, alpha);
|
|
1531
|
+
if (/^(rgb|hsl)a?\(/i.test(converted)) return converted;
|
|
1532
|
+
return `color-mix(in srgb, ${color} ${Math.round(Math.max(0, Math.min(1, alpha)) * 100)}%, transparent)`;
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* The color scheme the HOST's own preference resolves to, pushed in by the
|
|
1536
|
+
* browser half (the theme service knows it, custom themes included). `null`
|
|
1537
|
+
* means "unknown", which is the only case where the plugin falls back to the
|
|
1538
|
+
* preference the host's boot script published and to the OS query itself.
|
|
1539
|
+
*/
|
|
1540
|
+
let hostSchemeDark = null;
|
|
1541
|
+
function setHostScheme(dark) {
|
|
1542
|
+
hostSchemeDark = dark;
|
|
1543
|
+
}
|
|
1544
|
+
function resolveHostDark() {
|
|
1545
|
+
if (typeof hostSchemeDark === "boolean") return hostSchemeDark;
|
|
1546
|
+
const source = document.documentElement.dataset.dsThemeSource;
|
|
1547
|
+
if (source === "dark") return true;
|
|
1548
|
+
if (source === "light") return false;
|
|
1549
|
+
try {
|
|
1550
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
1551
|
+
} catch {
|
|
1552
|
+
return false;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Keep `data-ds-dark-theme` in the HOST's own form (a boolean attribute) while
|
|
1557
|
+
* the plugin does not own a palette.
|
|
1558
|
+
*
|
|
1559
|
+
* The plugin overwrites that flag whenever it owns a palette — including
|
|
1560
|
+
* REMOVING it to force a light one — and the host only re-projects the flag on a
|
|
1561
|
+
* theme change. So a flag the plugin dropped can stick: the host keeps painting
|
|
1562
|
+
* its light palette on a dark system, the readback then hands those light
|
|
1563
|
+
* surfaces back to the plugin, and the interface stays light until some
|
|
1564
|
+
* unrelated event happens to re-run an apply. Restoring the flag from the
|
|
1565
|
+
* resolved scheme closes that hole, and the write is skipped when it already
|
|
1566
|
+
* matches so this never churns the theme observer.
|
|
1567
|
+
*/
|
|
1568
|
+
function adoptHostScheme() {
|
|
1569
|
+
const dark = resolveHostDark();
|
|
1570
|
+
const current = document.body.getAttribute(DARK_ATTR);
|
|
1571
|
+
if (dark) {
|
|
1572
|
+
if (current !== "") document.body.setAttribute(DARK_ATTR, "");
|
|
1573
|
+
} else if (current !== null) document.body.removeAttribute(DARK_ATTR);
|
|
1574
|
+
}
|
|
1575
|
+
/** Re-read the host palette and repaint from it when it moved. Called while a
|
|
1576
|
+
* color-less rule is active (the host can re-project its palette at any time,
|
|
1577
|
+
* with no event of ours to hang a repaint on). */
|
|
1578
|
+
function refreshSystemTheme() {
|
|
1579
|
+
adoptHostScheme();
|
|
1580
|
+
invalidateHostPalette();
|
|
1581
|
+
applyCustomTokens(rOps());
|
|
1582
|
+
}
|
|
1395
1583
|
let pendingOps = null;
|
|
1396
1584
|
let tokensRaf = null;
|
|
1397
1585
|
function applyCustomTokens(ops) {
|
|
@@ -1407,26 +1595,38 @@ window.__ModuleLoader__.load({
|
|
|
1407
1595
|
}
|
|
1408
1596
|
let lastBgKey = "";
|
|
1409
1597
|
function applyCustomTokensNow(ops) {
|
|
1598
|
+
const src = palette();
|
|
1599
|
+
if (src === null) {
|
|
1600
|
+
clearCustomTokens();
|
|
1601
|
+
clearOwnedSurfaces();
|
|
1602
|
+
adoptHostScheme();
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
const { own, tokens } = src;
|
|
1410
1606
|
const [h, s, l] = rColor();
|
|
1411
|
-
const { tokens } = genTokens(h, s, l);
|
|
1412
1607
|
try {
|
|
1413
|
-
const forceDark = l < .55;
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
if (
|
|
1417
|
-
|
|
1418
|
-
|
|
1608
|
+
const forceDark = own && l < .55;
|
|
1609
|
+
const key = own ? `own:${h}|${s}|${l}` : `host:${HOST_SURFACE_TOKENS.map((n) => tokens[n] ?? "").join("|")}`;
|
|
1610
|
+
if (key !== baseTokenKey) {
|
|
1611
|
+
if (own) {
|
|
1612
|
+
if (forceDark) document.body.setAttribute(DARK_ATTR, OWN_SCHEME);
|
|
1613
|
+
else document.body.removeAttribute(DARK_ATTR);
|
|
1614
|
+
} else adoptHostScheme();
|
|
1615
|
+
const decls = own ? [`color-scheme:${forceDark ? "dark" : "light"}`] : [];
|
|
1419
1616
|
for (const [name, value] of Object.entries(tokens)) {
|
|
1420
1617
|
const opVar = OPACITY_VARS[name];
|
|
1421
1618
|
decls.push(`${name}:${opVar !== void 0 ? `var(${opVar})` : value}!important`);
|
|
1422
1619
|
}
|
|
1423
1620
|
ensureTokenStyle().textContent = `body{${decls.join(";")}}`;
|
|
1424
|
-
|
|
1425
|
-
|
|
1621
|
+
if (own) {
|
|
1622
|
+
for (const name of appliedTokenNames) document.body.style.removeProperty(name);
|
|
1623
|
+
appliedTokenNames = Object.keys(tokens);
|
|
1624
|
+
}
|
|
1625
|
+
baseTokenKey = key;
|
|
1426
1626
|
}
|
|
1427
1627
|
const root = document.documentElement;
|
|
1428
|
-
for (const g of OPACITY_TOKEN_GROUPS) for (const name of g.names) root.style.setProperty(OPACITY_VARS[name],
|
|
1429
|
-
root.style.setProperty("--dsh-any-op-menu-cordis",
|
|
1628
|
+
for (const g of OPACITY_TOKEN_GROUPS) for (const name of g.names) root.style.setProperty(OPACITY_VARS[name], withAlpha(tokens[name] ?? "#000", ops[g.part]));
|
|
1629
|
+
root.style.setProperty("--dsh-any-op-menu-cordis", withAlpha(tokens["--dsw-specific-menu"] ?? "#000", ops.input));
|
|
1430
1630
|
const bgKey = `${baseTokenKey}|${ops.bg}`;
|
|
1431
1631
|
if (bgKey !== lastBgKey) {
|
|
1432
1632
|
lastBgKey = bgKey;
|
|
@@ -1435,45 +1635,48 @@ window.__ModuleLoader__.load({
|
|
|
1435
1635
|
} catch {}
|
|
1436
1636
|
}
|
|
1437
1637
|
const SETTINGS_PANEL_SEL = "[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]";
|
|
1438
|
-
const SETTINGS_STYLE_RULE = `${SETTINGS_PANEL_SEL}{background:var(--dsh-any-bg-settings-surface,var(--dsw-alias-bg-layer-2));backdrop-filter:var(--dsh-any-blur-settings,none)
|
|
1638
|
+
const SETTINGS_STYLE_RULE = `${SETTINGS_PANEL_SEL}{background:var(--dsh-any-bg-settings-surface,var(--dsw-alias-bg-layer-2));backdrop-filter:var(--dsh-any-blur-settings,none);}html[${THEMED_ATTR}] ${SETTINGS_PANEL_SEL}{--dsw-alias-bg-layer-1:var(--dsh-any-bg-settings-layer-1);--dsw-alias-bg-layer-2:var(--dsh-any-bg-settings-layer-2);--dsw-alias-bg-layer-3:var(--dsh-any-bg-settings-layer-3)}${SETTINGS_PANEL_SEL} .dab-card{backdrop-filter:var(--dsh-any-blur-card-panels,none);-webkit-backdrop-filter:var(--dsh-any-blur-card-panels,none)}`;
|
|
1439
1639
|
const INPUT_BLUR_RULE = "[data-composer-card],[data-cordis-panel]{-webkit-backdrop-filter:var(--dsh-any-input-blur,none);backdrop-filter:var(--dsh-any-input-blur,none)}[data-cordis-panel]{--dsw-specific-menu:var(--dsh-any-op-menu-cordis)!important}";
|
|
1440
1640
|
function applyInputBlur(px) {
|
|
1441
1641
|
if (px > 0) document.documentElement.style.setProperty("--dsh-any-input-blur", `blur(${px}px)`);
|
|
1442
1642
|
else document.documentElement.style.removeProperty("--dsh-any-input-blur");
|
|
1443
1643
|
}
|
|
1444
1644
|
function applySettingsOverrides(op) {
|
|
1445
|
-
const
|
|
1446
|
-
const
|
|
1447
|
-
const
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1645
|
+
const tokens = palette()?.tokens ?? {};
|
|
1646
|
+
const root = document.documentElement;
|
|
1647
|
+
const write = (name, token) => {
|
|
1648
|
+
const value = tokens[token];
|
|
1649
|
+
if (value === void 0) root.style.removeProperty(name);
|
|
1650
|
+
else root.style.setProperty(name, withAlpha(value, op));
|
|
1651
|
+
};
|
|
1652
|
+
write("--dsh-any-bg-settings-surface", "--dsw-alias-bg-layer-2");
|
|
1653
|
+
write("--dsh-any-bg-settings-layer-1", "--dsw-alias-bg-layer-1");
|
|
1654
|
+
write("--dsh-any-bg-settings-layer-2", "--dsw-alias-bg-layer-2");
|
|
1655
|
+
write("--dsh-any-bg-settings-layer-3", "--dsw-alias-bg-layer-3");
|
|
1656
|
+
}
|
|
1657
|
+
const TRAJECTORY_STYLE_RULE = `html[${THEMED_ATTR}] [data-conversation-composer-overlay]{--dsw-alias-bg-layer-1:var(--dsh-any-traj-layer-1);--dsw-alias-bg-layer-2:var(--dsh-any-traj-layer-2);--dsw-alias-bg-layer-3:var(--dsh-any-traj-layer-3)}`;
|
|
1456
1658
|
function applyTrajectoryOverrides(op) {
|
|
1457
|
-
const
|
|
1458
|
-
const
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1659
|
+
const tokens = palette()?.tokens ?? {};
|
|
1660
|
+
const root = document.documentElement;
|
|
1661
|
+
const write = (name, token) => {
|
|
1662
|
+
const value = tokens[token];
|
|
1663
|
+
if (value === void 0) root.style.removeProperty(name);
|
|
1664
|
+
else root.style.setProperty(name, withAlpha(value, op));
|
|
1665
|
+
};
|
|
1666
|
+
write("--dsh-any-traj-layer-1", "--dsw-alias-bg-layer-1");
|
|
1667
|
+
write("--dsh-any-traj-layer-2", "--dsw-alias-bg-layer-2");
|
|
1668
|
+
write("--dsh-any-traj-layer-3", "--dsw-alias-bg-layer-3");
|
|
1465
1669
|
}
|
|
1466
1670
|
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)}";
|
|
1467
1671
|
/** Paint the file-preview panel's surface from its own slider. */
|
|
1468
1672
|
function applyRightbarOverrides(op) {
|
|
1469
1673
|
const root = document.documentElement;
|
|
1470
|
-
|
|
1674
|
+
const base = palette()?.tokens["--dsw-alias-bg-base"];
|
|
1675
|
+
if (base === void 0) {
|
|
1471
1676
|
root.style.removeProperty("--dsh-any-bg-rightbar");
|
|
1472
1677
|
return;
|
|
1473
1678
|
}
|
|
1474
|
-
|
|
1475
|
-
const base = genTokens(h, s, l).tokens["--dsw-alias-bg-base"];
|
|
1476
|
-
if (base !== void 0) root.style.setProperty("--dsh-any-bg-rightbar", toRgba(base, op));
|
|
1679
|
+
root.style.setProperty("--dsh-any-bg-rightbar", withAlpha(base, op));
|
|
1477
1680
|
}
|
|
1478
1681
|
/** Extra backdrop frost for the file-preview panel (0 = no frost of its own). */
|
|
1479
1682
|
function applyRightbarBlur(px) {
|
|
@@ -1542,14 +1745,20 @@ window.__ModuleLoader__.load({
|
|
|
1542
1745
|
* reducing the main-bg opacity stacked a second alpha onto the sidebar; moving
|
|
1543
1746
|
* the alpha onto the columns keeps the sidebar owned by its own slider. */
|
|
1544
1747
|
function applyPartOpacities(ops) {
|
|
1545
|
-
if (!rHasColor()) return;
|
|
1546
1748
|
discoverParts();
|
|
1547
1749
|
if (frameEl === null) return;
|
|
1548
|
-
const
|
|
1549
|
-
|
|
1750
|
+
const base = palette()?.tokens["--dsw-alias-bg-base"];
|
|
1751
|
+
if (base === void 0) {
|
|
1752
|
+
for (const el of [
|
|
1753
|
+
frameEl,
|
|
1754
|
+
centerEl,
|
|
1755
|
+
detailsEl
|
|
1756
|
+
]) el?.style.removeProperty("background");
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1550
1759
|
frameEl.style.background = "transparent";
|
|
1551
|
-
if (centerEl !== null) centerEl.style.background =
|
|
1552
|
-
if (detailsEl !== null) detailsEl.style.background =
|
|
1760
|
+
if (centerEl !== null) centerEl.style.background = withAlpha(base, ops.bg);
|
|
1761
|
+
if (detailsEl !== null) detailsEl.style.background = withAlpha(base, ops.bg);
|
|
1553
1762
|
}
|
|
1554
1763
|
/** Blur of the option panels inside the settings dialog (.dab-card), owned by
|
|
1555
1764
|
* the "dialog option panel" (card) blur slider. Written as a plugin-owned
|
|
@@ -1762,8 +1971,7 @@ window.__ModuleLoader__.load({
|
|
|
1762
1971
|
function applyViewCards() {
|
|
1763
1972
|
discoverParts();
|
|
1764
1973
|
if (centerEl === null) return;
|
|
1765
|
-
const
|
|
1766
|
-
const surface = genTokens(h, s, l).tokens["--dsw-alias-bg-layer-1"];
|
|
1974
|
+
const surface = palette()?.tokens["--dsw-alias-bg-layer-1"];
|
|
1767
1975
|
VIEW_CARDS.forEach((spec, i) => {
|
|
1768
1976
|
const target = discoverViewTarget(i, spec);
|
|
1769
1977
|
if (target === null) return;
|
|
@@ -1773,8 +1981,8 @@ window.__ModuleLoader__.load({
|
|
|
1773
1981
|
if (!plain) {
|
|
1774
1982
|
if (!target.hasAttribute(spec.mark)) stashCardPrev(target, spec.prev, false);
|
|
1775
1983
|
const borderAlpha = opacity > 0 ? Math.min(1, opacity * 1.5) : blurPx > 0 ? .35 : 0;
|
|
1776
|
-
target.style.background = surface !== void 0 ?
|
|
1777
|
-
target.style.border = surface !== void 0 ? `1px solid ${
|
|
1984
|
+
target.style.background = surface !== void 0 ? withAlpha(surface, opacity) : "transparent";
|
|
1985
|
+
target.style.border = surface !== void 0 ? `1px solid ${withAlpha(surface, borderAlpha)}` : "1px solid transparent";
|
|
1778
1986
|
target.style.borderRadius = "16px";
|
|
1779
1987
|
target.style.padding = "18px";
|
|
1780
1988
|
}
|
|
@@ -1806,31 +2014,38 @@ window.__ModuleLoader__.load({
|
|
|
1806
2014
|
let themeRaf = 0;
|
|
1807
2015
|
function reassertScheme() {
|
|
1808
2016
|
const [, , l] = rColor();
|
|
1809
|
-
if (l < .55) document.body.setAttribute(
|
|
1810
|
-
else document.body.removeAttribute(
|
|
2017
|
+
if (l < .55) document.body.setAttribute(DARK_ATTR, OWN_SCHEME);
|
|
2018
|
+
else document.body.removeAttribute(DARK_ATTR);
|
|
1811
2019
|
applyCustomTokens(rOps());
|
|
1812
2020
|
}
|
|
1813
2021
|
/** Re-assert the plugin's forced scheme whenever the host strips it, so a
|
|
1814
|
-
* refresh / cold-load / set-change never flashes a light frame.
|
|
2022
|
+
* refresh / cold-load / set-change never flashes a light frame. Also the point
|
|
2023
|
+
* where a host-side scheme flip is noticed while a color-less rule runs: that
|
|
2024
|
+
* rule paints from the host palette, so the readback is dropped and the
|
|
2025
|
+
* surfaces are re-emitted from the new one. */
|
|
1815
2026
|
function watchThemeResets() {
|
|
1816
2027
|
if (themeObserver !== null || typeof MutationObserver === "undefined") return () => void 0;
|
|
1817
2028
|
themeObserver = new MutationObserver(() => {
|
|
1818
|
-
|
|
1819
|
-
if (
|
|
2029
|
+
invalidateHostPalette();
|
|
2030
|
+
if (document.body.getAttribute(DARK_ATTR) === "dsh-background-by-model") return;
|
|
2031
|
+
if (!rHasColor()) {
|
|
2032
|
+
applyCustomTokens(rOps());
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
1820
2035
|
if (themeRaf !== 0) return;
|
|
1821
2036
|
themeRaf = requestAnimationFrame(() => {
|
|
1822
2037
|
themeRaf = 0;
|
|
1823
|
-
if (document.body.getAttribute(
|
|
2038
|
+
if (document.body.getAttribute(DARK_ATTR) === "dsh-background-by-model") return;
|
|
1824
2039
|
reassertScheme();
|
|
1825
2040
|
});
|
|
1826
2041
|
});
|
|
1827
2042
|
themeObserver.observe(document.body, {
|
|
1828
2043
|
attributes: true,
|
|
1829
|
-
attributeFilter: [
|
|
2044
|
+
attributeFilter: [DARK_ATTR]
|
|
1830
2045
|
});
|
|
1831
2046
|
themeObserver.observe(document.documentElement, {
|
|
1832
2047
|
attributes: true,
|
|
1833
|
-
attributeFilter: [
|
|
2048
|
+
attributeFilter: [DARK_ATTR]
|
|
1834
2049
|
});
|
|
1835
2050
|
return () => {
|
|
1836
2051
|
themeObserver?.disconnect();
|
|
@@ -2072,16 +2287,20 @@ window.__ModuleLoader__.load({
|
|
|
2072
2287
|
const url = rWp();
|
|
2073
2288
|
if (url) applyImageWp(url);
|
|
2074
2289
|
else if (wpEl !== null) dropWpContainer();
|
|
2075
|
-
if (rHasColor()) {
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2290
|
+
if (!rHasColor() && !baseTokenKey.startsWith("host:")) {
|
|
2291
|
+
clearCustomTokens();
|
|
2292
|
+
invalidateHostPalette();
|
|
2293
|
+
}
|
|
2294
|
+
if (!rHasColor()) adoptHostScheme();
|
|
2295
|
+
const src = palette();
|
|
2296
|
+
document.documentElement.toggleAttribute(THEMED_ATTR, src !== null);
|
|
2297
|
+
if (src === null) {
|
|
2080
2298
|
clearCustomTokens();
|
|
2081
|
-
|
|
2082
|
-
baseTokenKey = "";
|
|
2083
|
-
lastBgKey = "";
|
|
2299
|
+
clearOwnedSurfaces();
|
|
2084
2300
|
}
|
|
2301
|
+
applyCustomTokens(rOps());
|
|
2302
|
+
applySettingsOverrides(rSop());
|
|
2303
|
+
applyTrajectoryOverrides(rTrajectoryOpacity());
|
|
2085
2304
|
applyRightbarOverrides(rRightbarOpacity());
|
|
2086
2305
|
applyPartBlurs(rBlurs());
|
|
2087
2306
|
}
|
|
@@ -2091,23 +2310,17 @@ window.__ModuleLoader__.load({
|
|
|
2091
2310
|
tokenStyleEl?.remove();
|
|
2092
2311
|
tokenStyleEl = null;
|
|
2093
2312
|
removeViewCards();
|
|
2094
|
-
document.
|
|
2313
|
+
document.documentElement.removeAttribute(THEMED_ATTR);
|
|
2095
2314
|
document.body.style.removeProperty("color-scheme");
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
document.documentElement.style.removeProperty("--dsh-any-bg-settings-layer-3");
|
|
2100
|
-
document.documentElement.style.removeProperty("--dsh-any-traj-layer-1");
|
|
2101
|
-
document.documentElement.style.removeProperty("--dsh-any-traj-layer-2");
|
|
2102
|
-
document.documentElement.style.removeProperty("--dsh-any-traj-layer-3");
|
|
2315
|
+
clearOwnedSurfaces();
|
|
2316
|
+
adoptHostScheme();
|
|
2317
|
+
invalidateHostPalette();
|
|
2103
2318
|
document.documentElement.style.removeProperty("--dsh-any-blur-settings");
|
|
2104
2319
|
document.documentElement.style.removeProperty("--dsh-any-blur-card-panels");
|
|
2105
2320
|
document.documentElement.style.removeProperty("--dsh-any-input-blur");
|
|
2106
2321
|
document.documentElement.style.removeProperty("--dsh-any-bg-rightbar");
|
|
2107
2322
|
document.documentElement.style.removeProperty("--dsh-any-blur-rightbar");
|
|
2108
2323
|
for (const v of Object.values(OPACITY_VARS)) document.documentElement.style.removeProperty(v);
|
|
2109
|
-
baseTokenKey = "";
|
|
2110
|
-
lastBgKey = "";
|
|
2111
2324
|
if (tokensRaf !== null) {
|
|
2112
2325
|
cancelAnimationFrame(tokensRaf);
|
|
2113
2326
|
tokensRaf = null;
|
|
@@ -2119,9 +2332,6 @@ window.__ModuleLoader__.load({
|
|
|
2119
2332
|
setBlur(sidebarEl, 0);
|
|
2120
2333
|
setBlur(centerEl, 0);
|
|
2121
2334
|
setBlur(detailsEl, 0);
|
|
2122
|
-
if (frameEl !== null) frameEl.style.removeProperty("background");
|
|
2123
|
-
if (centerEl !== null) centerEl.style.removeProperty("background");
|
|
2124
|
-
if (detailsEl !== null) detailsEl.style.removeProperty("background");
|
|
2125
2335
|
stopWatchingParts();
|
|
2126
2336
|
}
|
|
2127
2337
|
//#endregion
|
|
@@ -3919,6 +4129,23 @@ window.__ModuleLoader__.load({
|
|
|
3919
4129
|
setExtracting(false);
|
|
3920
4130
|
}
|
|
3921
4131
|
};
|
|
4132
|
+
/**
|
|
4133
|
+
* Leaving "follow the system theme" must not hand the user a color that has
|
|
4134
|
+
* nothing to do with the wallpaper they just picked, so this tries the image
|
|
4135
|
+
* first and only falls back to the seed. (`extractColor` is the same pass the
|
|
4136
|
+
* extract button runs and returns false when nothing vivid was found.)
|
|
4137
|
+
*/
|
|
4138
|
+
const onPickColor = async () => {
|
|
4139
|
+
if (url !== null) {
|
|
4140
|
+
setExtracting(true);
|
|
4141
|
+
try {
|
|
4142
|
+
if (await p.extractColor(rule.id)) return;
|
|
4143
|
+
} catch {} finally {
|
|
4144
|
+
setExtracting(false);
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
p.setRule(rule.id, { color: SEED_COLOR });
|
|
4148
|
+
};
|
|
3922
4149
|
const cls = `dab-rule${active ? " is-active" : ""}${rule.enabled ? "" : " is-off"}`;
|
|
3923
4150
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3924
4151
|
className: cls,
|
|
@@ -4110,25 +4337,34 @@ window.__ModuleLoader__.load({
|
|
|
4110
4337
|
className: "dab-rule-section-title",
|
|
4111
4338
|
children: t("ruleColor")
|
|
4112
4339
|
}),
|
|
4113
|
-
rule.color === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4340
|
+
rule.color === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4342
|
+
className: "dab-chip-row",
|
|
4343
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4344
|
+
type: "button",
|
|
4345
|
+
className: "dab-btn",
|
|
4346
|
+
disabled: extracting,
|
|
4347
|
+
onClick: () => void onPickColor(),
|
|
4348
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropletIcon, { size: 14 }), extracting ? t("extracting") : t("ruleColorPick")]
|
|
4349
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4350
|
+
type: "button",
|
|
4351
|
+
className: "dab-btn",
|
|
4352
|
+
disabled: url === null || extracting,
|
|
4353
|
+
onClick: () => void onExtract(),
|
|
4354
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SparkleIcon, { size: 14 }), extracting ? t("extracting") : t("ruleColorExtract")]
|
|
4355
|
+
})]
|
|
4356
|
+
}),
|
|
4357
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4358
|
+
className: "dab-hint",
|
|
4359
|
+
style: { marginTop: 8 },
|
|
4360
|
+
children: t("ruleColorNoneHint")
|
|
4361
|
+
}),
|
|
4362
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4363
|
+
className: "dab-hint",
|
|
4364
|
+
style: { marginTop: 6 },
|
|
4365
|
+
children: t("ruleColorPickHint")
|
|
4366
|
+
})
|
|
4367
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4132
4368
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4133
4369
|
style: {
|
|
4134
4370
|
display: "flex",
|
|
@@ -4522,7 +4758,7 @@ window.__ModuleLoader__.load({
|
|
|
4522
4758
|
const styleEl = document.createElement("style");
|
|
4523
4759
|
styleEl.dataset.plugin = "dsh-background-by-model";
|
|
4524
4760
|
markOwnSheet(styleEl);
|
|
4525
|
-
styleEl.textContent = `body[data-ds-dark-theme="
|
|
4761
|
+
styleEl.textContent = `body[data-ds-dark-theme="${OWN_SCHEME}"]::before{content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;background:radial-gradient(ellipse 80% 60% at 50% 0%,rgba(255,255,255,0.03) 0%,transparent 60%)}${SETTINGS_STYLE_RULE}${TRAJECTORY_STYLE_RULE}${RIGHTBAR_STYLE_RULE}${INPUT_BLUR_RULE}[data-composer-card] textarea::placeholder,[data-composer-card] input::placeholder,[data-composer-card] [contenteditable]::placeholder,[data-cordis-panel] input::placeholder,[data-cordis-panel] textarea::placeholder,.dab-input::placeholder,.dab-input textarea::placeholder,.dab-input input::placeholder{color:var(--dsh-any-placeholder,var(--dsw-alias-label-caption,#8a8f98))!important;font-style:italic;opacity:.85}`;
|
|
4526
4762
|
document.head.appendChild(styleEl);
|
|
4527
4763
|
ctx.effect(() => () => {
|
|
4528
4764
|
styleEl?.parentNode?.removeChild(styleEl);
|
|
@@ -4562,20 +4798,38 @@ window.__ModuleLoader__.load({
|
|
|
4562
4798
|
rev++;
|
|
4563
4799
|
bound?.sync(rWp(), rev, rulesRev, modelLabel !== "" ? modelLabel : modelText, modelSource, modelNote, activeRuleId, activeMatched);
|
|
4564
4800
|
};
|
|
4801
|
+
/**
|
|
4802
|
+
* Publish the scheme the host's own preference resolves to. The theme service
|
|
4803
|
+
* is the only place that knows it (a custom active theme included); the
|
|
4804
|
+
* wallpaper layer needs it to hand `data-ds-dark-theme` back in the host's own
|
|
4805
|
+
* form while a color-less rule follows that theme, instead of leaving the flag
|
|
4806
|
+
* off — which pins the host to its LIGHT palette on a dark system.
|
|
4807
|
+
*/
|
|
4808
|
+
const syncHostScheme = () => {
|
|
4809
|
+
try {
|
|
4810
|
+
setHostScheme(ctx.theme.getTheme().active.colorScheme === "dark");
|
|
4811
|
+
} catch {
|
|
4812
|
+
setHostScheme(null);
|
|
4813
|
+
}
|
|
4814
|
+
};
|
|
4565
4815
|
/** Resolve the active rule for the current model and repaint everything. */
|
|
4566
4816
|
const applyActive = () => {
|
|
4567
4817
|
const { rule, matched } = matchRule(cfg.rules, modelText);
|
|
4568
4818
|
setActive(rule === null ? null : rule.id, matched);
|
|
4569
4819
|
const color = rule === null ? null : rule.color;
|
|
4570
4820
|
if (skinTimer !== null) window.clearTimeout(skinTimer);
|
|
4571
|
-
|
|
4821
|
+
if (color === null) {
|
|
4822
|
+
skinTimer = null;
|
|
4823
|
+
dropCustom();
|
|
4824
|
+
} else skinTimer = window.setTimeout(() => {
|
|
4572
4825
|
skinTimer = null;
|
|
4573
|
-
|
|
4574
|
-
else registerCustom(color[0], color[1], color[2]);
|
|
4826
|
+
registerCustom(color[0], color[1], color[2]);
|
|
4575
4827
|
}, 60);
|
|
4828
|
+
syncHostScheme();
|
|
4576
4829
|
applyWp();
|
|
4577
4830
|
sync();
|
|
4578
4831
|
};
|
|
4832
|
+
syncHostScheme();
|
|
4579
4833
|
applyWp();
|
|
4580
4834
|
sync();
|
|
4581
4835
|
watchParts();
|
|
@@ -4625,6 +4879,7 @@ window.__ModuleLoader__.load({
|
|
|
4625
4879
|
teardownWp();
|
|
4626
4880
|
}, "dsh-background-by-model: wp cleanup");
|
|
4627
4881
|
ctx.effect(() => ctx.on("theme/change", () => {
|
|
4882
|
+
syncHostScheme();
|
|
4628
4883
|
if (activeRuleColor() !== null) {
|
|
4629
4884
|
const snapshot = ctx.theme.getTheme();
|
|
4630
4885
|
if (snapshot.preference !== CUSTOM_ID && snapshot.themes.some((t) => t.id === CUSTOM_ID)) ctx.theme.setTheme(CUSTOM_ID);
|
|
@@ -4927,6 +5182,7 @@ window.__ModuleLoader__.load({
|
|
|
4927
5182
|
navIconObserver = null;
|
|
4928
5183
|
}, "dsh-background-by-model: nav icon watch");
|
|
4929
5184
|
const restoreSaved = () => {
|
|
5185
|
+
syncHostScheme();
|
|
4930
5186
|
const color = activeRuleColor();
|
|
4931
5187
|
if (color !== null) {
|
|
4932
5188
|
const snapshot = ctx.theme.getTheme();
|
|
@@ -4940,8 +5196,12 @@ window.__ModuleLoader__.load({
|
|
|
4940
5196
|
restoreTimers.forEach((id) => window.clearTimeout(id));
|
|
4941
5197
|
}, "dsh-background-by-model: boot restore");
|
|
4942
5198
|
const watchdogId = window.setInterval(() => {
|
|
5199
|
+
syncHostScheme();
|
|
4943
5200
|
const color = activeRuleColor();
|
|
4944
|
-
if (color === null)
|
|
5201
|
+
if (color === null) {
|
|
5202
|
+
refreshSystemTheme();
|
|
5203
|
+
return;
|
|
5204
|
+
}
|
|
4945
5205
|
const snapshot = ctx.theme.getTheme();
|
|
4946
5206
|
let changed = false;
|
|
4947
5207
|
if (!snapshot.themes.some((t) => t.id === CUSTOM_ID)) {
|