@nonamelego/dsh-catppuccin 0.2.11 → 0.3.0
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 +6 -1
- package/lib/client.js +163 -72
- package/lib/client.js.map +1 -1
- package/lib/index.js +30 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,7 +152,8 @@ pnpm --dir C:\Users\LeGo\.dsh\profiles\web add link:D:\Vibe-Coding\dsh-catppucci
|
|
|
152
152
|
2. 进入 **设置 → 常规**。
|
|
153
153
|
3. 在 **外观** 区域下方找到 **Catppuccin** 行,选择主题:
|
|
154
154
|
**Latte**(浅色)、**Frappé**、**Macchiato** 或 **Mocha**(深色)。
|
|
155
|
-
4. 选择 **跟随系统**
|
|
155
|
+
4. 选择 **跟随系统** 则回退到官方主题——会还原你启用 Catppuccin 之前
|
|
156
|
+
的官方偏好(浅色 / 深色 / 跟随系统),而不是强制重置。
|
|
156
157
|
|
|
157
158
|
### 玻璃质感
|
|
158
159
|
|
|
@@ -162,6 +163,8 @@ pnpm --dir C:\Users\LeGo\.dsh\profiles\web add link:D:\Vibe-Coding\dsh-catppucci
|
|
|
162
163
|
关闭即完全还原原生界面(无需刷新)。
|
|
163
164
|
- **模式**:**云母效果**把界面改成悬浮磨砂卡片;**兼容模式**保持原版排版,
|
|
164
165
|
只把材质换成玻璃。
|
|
166
|
+
- **预设**:**清透 / 标准 / 磨砂** 三档一键套用;想微调再用下面的滑条
|
|
167
|
+
(当前旋钮值与某档一致时该档高亮)。
|
|
165
168
|
- **玻璃模糊度**(0–40 px)、**磨砂度**(0–100%):控制玻璃的模糊半径与
|
|
166
169
|
不透明度。
|
|
167
170
|
- **背景亮度**:深色模式 0–50 压暗、浅色模式 50–100 提亮(50 为原样),
|
|
@@ -178,6 +181,8 @@ localStorage 只作为即时缓存与多标签页同步——**DSH Desktop** 每
|
|
|
178
181
|
|
|
179
182
|
在 **设置 → 常规** 的 **玻璃质感** 正下方找到 **检查 Catppuccin 插件更新** 行:
|
|
180
183
|
|
|
184
|
+
- 打开设置页会自动静默检查一次(结果就地显示),也可以随时点 **检查更新**
|
|
185
|
+
手动复查;宿主侧对检查结果缓存 5 分钟,反复打开设置不会重复请求 registry。
|
|
181
186
|
- 点击 **检查更新**,插件宿主会查询 npm registry 上本插件(`dsh-catppuccin`)
|
|
182
187
|
的最新版本,并与当前安装版本比较(含预发布版本的语义化版本比较)。
|
|
183
188
|
- 已是最新 → 显示当前版本号;发现新版 → 显示新版本号,并给出可复制的
|
package/lib/client.js
CHANGED
|
@@ -129,6 +129,10 @@ window.__ModuleLoader__.load({
|
|
|
129
129
|
"glass.modeMica": "云母效果",
|
|
130
130
|
"glass.modeCompat": "兼容模式",
|
|
131
131
|
"glass.modeHint": "云母效果把界面改成悬浮磨砂卡片;兼容模式保持原版排版,只换玻璃材质",
|
|
132
|
+
"glass.presets": "预设",
|
|
133
|
+
"glass.presetClear": "清透",
|
|
134
|
+
"glass.presetStandard": "标准",
|
|
135
|
+
"glass.presetFrosted": "磨砂",
|
|
132
136
|
"glass.blur": "玻璃模糊度",
|
|
133
137
|
"glass.frost": "磨砂度",
|
|
134
138
|
"glass.brightness": "背景亮度",
|
|
@@ -177,6 +181,10 @@ window.__ModuleLoader__.load({
|
|
|
177
181
|
"glass.modeMica": "Mica",
|
|
178
182
|
"glass.modeCompat": "Compatibility",
|
|
179
183
|
"glass.modeHint": "Mica restyles the UI into floating frosted cards; Compatibility keeps the stock layout and only swaps the material to glass",
|
|
184
|
+
"glass.presets": "Presets",
|
|
185
|
+
"glass.presetClear": "Clear",
|
|
186
|
+
"glass.presetStandard": "Standard",
|
|
187
|
+
"glass.presetFrosted": "Frosted",
|
|
180
188
|
"glass.blur": "Glass blur",
|
|
181
189
|
"glass.frost": "Frost",
|
|
182
190
|
"glass.brightness": "Backdrop brightness",
|
|
@@ -1029,6 +1037,67 @@ window.__ModuleLoader__.load({
|
|
|
1029
1037
|
observer.disconnect();
|
|
1030
1038
|
};
|
|
1031
1039
|
}
|
|
1040
|
+
/** Host route answering the durable state (GET reads, PUT writes). */
|
|
1041
|
+
const STATE_ROUTE_PATH = "/catppuccin/state";
|
|
1042
|
+
/** The four registered Catppuccin theme ids. MUST stay in sync with the
|
|
1043
|
+
* `themeId` of `CATPPUCCIN_FLAVORS` in `src/client/palettes.ts` — guarded by
|
|
1044
|
+
* `tests/state.spec.ts` — because the persisted flavour value IS the theme id. */
|
|
1045
|
+
const CATPPUCCIN_THEME_IDS = [
|
|
1046
|
+
"catppuccin-latte",
|
|
1047
|
+
"catppuccin-frappe",
|
|
1048
|
+
"catppuccin-macchiato",
|
|
1049
|
+
"catppuccin-mocha"
|
|
1050
|
+
];
|
|
1051
|
+
/** Shipped glass defaults — the single source of truth; the client glass layer
|
|
1052
|
+
* (`src/client/glass/glass-layer.ts`) derives its knob defaults from here. */
|
|
1053
|
+
const DEFAULT_GLASS = {
|
|
1054
|
+
enabled: false,
|
|
1055
|
+
mode: "mica",
|
|
1056
|
+
blur: 2,
|
|
1057
|
+
frost: 20,
|
|
1058
|
+
brightness: 50
|
|
1059
|
+
};
|
|
1060
|
+
/** A fully default state: no Catppuccin flavour and no glass. */
|
|
1061
|
+
function defaultState() {
|
|
1062
|
+
return {
|
|
1063
|
+
version: 1,
|
|
1064
|
+
flavor: "off",
|
|
1065
|
+
glass: { ...DEFAULT_GLASS }
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
/** Clamp a finite number into [min, max]; non-finite values fall back. */
|
|
1069
|
+
function clampFinite(value, min, max, fallback) {
|
|
1070
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : fallback;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Normalize arbitrary input (JSON from disk or the wire) into a valid state:
|
|
1074
|
+
* unknown/missing fields fall back to defaults, out-of-range numbers clamp,
|
|
1075
|
+
* and unknown flavours/invalid enums fall back too. The Host applies this on
|
|
1076
|
+
* both read and write so a corrupt file or a hand-crafted payload can never
|
|
1077
|
+
* poison the plugin's settings.
|
|
1078
|
+
*/
|
|
1079
|
+
function sanitizeState(input) {
|
|
1080
|
+
const state = defaultState();
|
|
1081
|
+
if (typeof input !== "object" || input === null) return state;
|
|
1082
|
+
const raw = input;
|
|
1083
|
+
const flavor = raw.flavor;
|
|
1084
|
+
if (typeof flavor === "string" && CATPPUCCIN_THEME_IDS.includes(flavor)) state.flavor = flavor;
|
|
1085
|
+
else if (flavor === "off") state.flavor = "off";
|
|
1086
|
+
const glass = typeof raw.glass === "object" && raw.glass !== null ? raw.glass : {};
|
|
1087
|
+
state.glass.enabled = glass.enabled === true;
|
|
1088
|
+
state.glass.mode = glass.mode === "compat" ? "compat" : "mica";
|
|
1089
|
+
state.glass.blur = clampFinite(glass.blur, 0, 40, DEFAULT_GLASS.blur);
|
|
1090
|
+
state.glass.frost = clampFinite(glass.frost, 0, 100, DEFAULT_GLASS.frost);
|
|
1091
|
+
state.glass.brightness = clampFinite(glass.brightness, 0, 100, DEFAULT_GLASS.brightness);
|
|
1092
|
+
return state;
|
|
1093
|
+
}
|
|
1094
|
+
/** Whether a normalized state carries nothing beyond the shipped defaults —
|
|
1095
|
+
* i.e. the user never actually chose anything worth persisting. Used to tell
|
|
1096
|
+
* "no durable state yet" apart from "an explicit default choice". */
|
|
1097
|
+
function isDefaultState(state) {
|
|
1098
|
+
const expected = defaultState();
|
|
1099
|
+
return state.flavor === expected.flavor && state.glass.enabled === expected.glass.enabled && state.glass.mode === expected.glass.mode && state.glass.blur === expected.glass.blur && state.glass.frost === expected.glass.frost && state.glass.brightness === expected.glass.brightness;
|
|
1100
|
+
}
|
|
1032
1101
|
//#endregion
|
|
1033
1102
|
//#region src/client/glass/glass-layer.ts
|
|
1034
1103
|
/** html attribute selecting the glass layer: CSS hooks and page effects. */
|
|
@@ -1039,18 +1108,21 @@ window.__ModuleLoader__.load({
|
|
|
1039
1108
|
const GLASS_COMPAT_ATTRIBUTE = "data-dsh-glass-compat";
|
|
1040
1109
|
/** localStorage key carrying the layer enable flag. */
|
|
1041
1110
|
const GLASS_ENABLED_KEY = "dsh.catppuccin.glass.enabled";
|
|
1111
|
+
/** Default state when nothing is stored yet: off (the stock UI stays stock). */
|
|
1112
|
+
const DEFAULT_ENABLED = DEFAULT_GLASS.enabled;
|
|
1042
1113
|
/**
|
|
1043
|
-
* Shipped knob defaults —
|
|
1114
|
+
* Shipped knob defaults — the knob-only view of `DEFAULT_GLASS` in
|
|
1115
|
+
* `src/state.ts` (the single source of truth, inlined into both bundles).
|
|
1116
|
+
* The shipped look aligns with the reference project
|
|
1044
1117
|
* (DSH-Transparent-UI-Plugin / Aqua): mica mode, blur 2px, frost 20
|
|
1045
1118
|
* (the 0-100 slider maps to a 0-1.4 alpha multiplier via frost/50, so 20
|
|
1046
|
-
* reads as a light frost) and neutral backdrop brightness.
|
|
1047
|
-
* with `DEFAULT_GLASS` in `src/state.ts` (guarded by `tests/state.spec.ts`).
|
|
1119
|
+
* reads as a light frost) and neutral backdrop brightness.
|
|
1048
1120
|
*/
|
|
1049
1121
|
const SETTINGS_DEFAULTS = {
|
|
1050
|
-
mode:
|
|
1051
|
-
blur:
|
|
1052
|
-
frost:
|
|
1053
|
-
brightness:
|
|
1122
|
+
mode: DEFAULT_GLASS.mode,
|
|
1123
|
+
blur: DEFAULT_GLASS.blur,
|
|
1124
|
+
frost: DEFAULT_GLASS.frost,
|
|
1125
|
+
brightness: DEFAULT_GLASS.brightness
|
|
1054
1126
|
};
|
|
1055
1127
|
/** Numeric knob keys and their localStorage names. */
|
|
1056
1128
|
const NUMERIC_KEYS = {
|
|
@@ -1097,9 +1169,9 @@ window.__ModuleLoader__.load({
|
|
|
1097
1169
|
function readEnabled() {
|
|
1098
1170
|
try {
|
|
1099
1171
|
const raw = localStorage.getItem(GLASS_ENABLED_KEY);
|
|
1100
|
-
return raw === null ?
|
|
1172
|
+
return raw === null ? DEFAULT_ENABLED : raw === "true";
|
|
1101
1173
|
} catch {
|
|
1102
|
-
return
|
|
1174
|
+
return DEFAULT_ENABLED;
|
|
1103
1175
|
}
|
|
1104
1176
|
}
|
|
1105
1177
|
/** Persist the enable flag (storage failures keep the in-memory state). */
|
|
@@ -1430,6 +1502,33 @@ window.__ModuleLoader__.load({
|
|
|
1430
1502
|
}, option.id))
|
|
1431
1503
|
});
|
|
1432
1504
|
}
|
|
1505
|
+
/** One-click material presets — blur/frost/brightness triples the row applies
|
|
1506
|
+
* through the existing setters (the debounced persist coalesces the burst
|
|
1507
|
+
* into one Host write). Brightness stays neutral (50) so every preset works
|
|
1508
|
+
* in both schemes; the sliders remain for fine tuning. */
|
|
1509
|
+
const GLASS_PRESETS = [
|
|
1510
|
+
{
|
|
1511
|
+
id: "clear",
|
|
1512
|
+
key: "glass.presetClear",
|
|
1513
|
+
blur: 0,
|
|
1514
|
+
frost: 8,
|
|
1515
|
+
brightness: 50
|
|
1516
|
+
},
|
|
1517
|
+
{
|
|
1518
|
+
id: "standard",
|
|
1519
|
+
key: "glass.presetStandard",
|
|
1520
|
+
blur: SETTINGS_DEFAULTS.blur,
|
|
1521
|
+
frost: SETTINGS_DEFAULTS.frost,
|
|
1522
|
+
brightness: SETTINGS_DEFAULTS.brightness
|
|
1523
|
+
},
|
|
1524
|
+
{
|
|
1525
|
+
id: "frosted",
|
|
1526
|
+
key: "glass.presetFrosted",
|
|
1527
|
+
blur: 12,
|
|
1528
|
+
frost: 45,
|
|
1529
|
+
brightness: 50
|
|
1530
|
+
}
|
|
1531
|
+
];
|
|
1433
1532
|
/**
|
|
1434
1533
|
* Render the glass row: title, the master switch, and — while enabled — the
|
|
1435
1534
|
* mode picker and every knob.
|
|
@@ -1441,6 +1540,7 @@ window.__ModuleLoader__.load({
|
|
|
1441
1540
|
const bgMin = dark ? 0 : 50;
|
|
1442
1541
|
const bgMax = dark ? 50 : 100;
|
|
1443
1542
|
const bgDisplay = Math.min(bgMax, Math.max(bgMin, brightness));
|
|
1543
|
+
const activePreset = GLASS_PRESETS.find((p) => p.blur === blur && p.frost === frost && p.brightness === brightness)?.id ?? "";
|
|
1444
1544
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1445
1545
|
className: GlassRow_module_css_default.group,
|
|
1446
1546
|
children: [
|
|
@@ -1497,6 +1597,27 @@ window.__ModuleLoader__.load({
|
|
|
1497
1597
|
className: GlassRow_module_css_default.rowHint,
|
|
1498
1598
|
children: t("glass.modeHint")
|
|
1499
1599
|
}),
|
|
1600
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1601
|
+
className: GlassRow_module_css_default.row,
|
|
1602
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1603
|
+
className: GlassRow_module_css_default.rowLabel,
|
|
1604
|
+
children: t("glass.presets")
|
|
1605
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Segmented, {
|
|
1606
|
+
label: t("glass.presets"),
|
|
1607
|
+
value: activePreset,
|
|
1608
|
+
options: GLASS_PRESETS.map((p) => ({
|
|
1609
|
+
id: p.id,
|
|
1610
|
+
label: t(p.key)
|
|
1611
|
+
})),
|
|
1612
|
+
onSelect: (id) => {
|
|
1613
|
+
const preset = GLASS_PRESETS.find((p) => p.id === id);
|
|
1614
|
+
if (preset === void 0) return;
|
|
1615
|
+
setBlur(preset.blur);
|
|
1616
|
+
setFrost(preset.frost);
|
|
1617
|
+
setBrightness(preset.brightness);
|
|
1618
|
+
}
|
|
1619
|
+
})]
|
|
1620
|
+
}),
|
|
1500
1621
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Knob, {
|
|
1501
1622
|
label: t("glass.blur"),
|
|
1502
1623
|
value: blur,
|
|
@@ -1578,7 +1699,9 @@ window.__ModuleLoader__.load({
|
|
|
1578
1699
|
}
|
|
1579
1700
|
/**
|
|
1580
1701
|
* Render the update-check row: title, description, a check button, and the
|
|
1581
|
-
* verdict once checked.
|
|
1702
|
+
* verdict once checked. The check also runs once automatically when the row
|
|
1703
|
+
* mounts (the Host caches the verdict for 5 minutes, so reopening settings
|
|
1704
|
+
* does not re-hit the registry).
|
|
1582
1705
|
* @param props - composed slot props.
|
|
1583
1706
|
* @returns the row element tree.
|
|
1584
1707
|
*/
|
|
@@ -1601,6 +1724,9 @@ window.__ModuleLoader__.load({
|
|
|
1601
1724
|
setPhase("done");
|
|
1602
1725
|
}
|
|
1603
1726
|
};
|
|
1727
|
+
(0, react.useEffect)(() => {
|
|
1728
|
+
runCheck();
|
|
1729
|
+
}, []);
|
|
1604
1730
|
const buttonStyle = {
|
|
1605
1731
|
display: "inline-flex",
|
|
1606
1732
|
alignItems: "center",
|
|
@@ -1803,67 +1929,6 @@ window.__ModuleLoader__.load({
|
|
|
1803
1929
|
`${"@nonamelego/dsh-catppuccin".replace("/", "%2F")}`;
|
|
1804
1930
|
/** Host route the Client row fetches (exact match, same origin). */
|
|
1805
1931
|
const UPDATE_ROUTE_PATH = "/catppuccin/check-update";
|
|
1806
|
-
/** Host route answering the durable state (GET reads, PUT writes). */
|
|
1807
|
-
const STATE_ROUTE_PATH = "/catppuccin/state";
|
|
1808
|
-
/** The four registered Catppuccin theme ids. MUST stay in sync with the
|
|
1809
|
-
* `themeId` of `CATPPUCCIN_FLAVORS` in `src/client/palettes.ts` — guarded by
|
|
1810
|
-
* `tests/state.spec.ts` — because the persisted flavour value IS the theme id. */
|
|
1811
|
-
const CATPPUCCIN_THEME_IDS = [
|
|
1812
|
-
"catppuccin-latte",
|
|
1813
|
-
"catppuccin-frappe",
|
|
1814
|
-
"catppuccin-macchiato",
|
|
1815
|
-
"catppuccin-mocha"
|
|
1816
|
-
];
|
|
1817
|
-
/** Shipped glass defaults — aligned with `SETTINGS_DEFAULTS` in
|
|
1818
|
-
* `src/client/glass/glass-layer.ts` (guarded by `tests/state.spec.ts`). */
|
|
1819
|
-
const DEFAULT_GLASS = {
|
|
1820
|
-
enabled: false,
|
|
1821
|
-
mode: "mica",
|
|
1822
|
-
blur: 2,
|
|
1823
|
-
frost: 20,
|
|
1824
|
-
brightness: 50
|
|
1825
|
-
};
|
|
1826
|
-
/** A fully default state: no Catppuccin flavour and no glass. */
|
|
1827
|
-
function defaultState() {
|
|
1828
|
-
return {
|
|
1829
|
-
version: 1,
|
|
1830
|
-
flavor: "off",
|
|
1831
|
-
glass: { ...DEFAULT_GLASS }
|
|
1832
|
-
};
|
|
1833
|
-
}
|
|
1834
|
-
/** Clamp a finite number into [min, max]; non-finite values fall back. */
|
|
1835
|
-
function clampFinite(value, min, max, fallback) {
|
|
1836
|
-
return typeof value === "number" && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : fallback;
|
|
1837
|
-
}
|
|
1838
|
-
/**
|
|
1839
|
-
* Normalize arbitrary input (JSON from disk or the wire) into a valid state:
|
|
1840
|
-
* unknown/missing fields fall back to defaults, out-of-range numbers clamp,
|
|
1841
|
-
* and unknown flavours/invalid enums fall back too. The Host applies this on
|
|
1842
|
-
* both read and write so a corrupt file or a hand-crafted payload can never
|
|
1843
|
-
* poison the plugin's settings.
|
|
1844
|
-
*/
|
|
1845
|
-
function sanitizeState(input) {
|
|
1846
|
-
const state = defaultState();
|
|
1847
|
-
if (typeof input !== "object" || input === null) return state;
|
|
1848
|
-
const raw = input;
|
|
1849
|
-
const flavor = raw.flavor;
|
|
1850
|
-
if (typeof flavor === "string" && CATPPUCCIN_THEME_IDS.includes(flavor)) state.flavor = flavor;
|
|
1851
|
-
else if (flavor === "off") state.flavor = "off";
|
|
1852
|
-
const glass = typeof raw.glass === "object" && raw.glass !== null ? raw.glass : {};
|
|
1853
|
-
state.glass.enabled = glass.enabled === true;
|
|
1854
|
-
state.glass.mode = glass.mode === "compat" ? "compat" : "mica";
|
|
1855
|
-
state.glass.blur = clampFinite(glass.blur, 0, 40, DEFAULT_GLASS.blur);
|
|
1856
|
-
state.glass.frost = clampFinite(glass.frost, 0, 100, DEFAULT_GLASS.frost);
|
|
1857
|
-
state.glass.brightness = clampFinite(glass.brightness, 0, 100, DEFAULT_GLASS.brightness);
|
|
1858
|
-
return state;
|
|
1859
|
-
}
|
|
1860
|
-
/** Whether a normalized state carries nothing beyond the shipped defaults —
|
|
1861
|
-
* i.e. the user never actually chose anything worth persisting. Used to tell
|
|
1862
|
-
* "no durable state yet" apart from "an explicit default choice". */
|
|
1863
|
-
function isDefaultState(state) {
|
|
1864
|
-
const expected = defaultState();
|
|
1865
|
-
return state.flavor === expected.flavor && state.glass.enabled === expected.glass.enabled && state.glass.mode === expected.glass.mode && state.glass.blur === expected.glass.blur && state.glass.frost === expected.glass.frost && state.glass.brightness === expected.glass.brightness;
|
|
1866
|
-
}
|
|
1867
1932
|
//#endregion
|
|
1868
1933
|
//#region src/client/state-sync.ts
|
|
1869
1934
|
/**
|
|
@@ -1981,6 +2046,28 @@ window.__ModuleLoader__.load({
|
|
|
1981
2046
|
localStorage.setItem(FLAVOR_STORAGE_KEY, choice);
|
|
1982
2047
|
} catch {}
|
|
1983
2048
|
}
|
|
2049
|
+
/** localStorage key recording the last built-in theme preference. */
|
|
2050
|
+
const RESTORE_STORAGE_KEY = "dsh.catppuccin.restore";
|
|
2051
|
+
/** Remember a built-in preference (system/light/dark) whenever the runtime is
|
|
2052
|
+
* not on a Catppuccin flavour, so switching the plugin off restores the
|
|
2053
|
+
* user's pre-plugin choice instead of dropping them onto 'system'. The boot
|
|
2054
|
+
* preference is the settings-document value, so this survives Desktop's
|
|
2055
|
+
* per-launch port churn without joining the durable state schema. */
|
|
2056
|
+
function rememberBuiltinPreference(preference) {
|
|
2057
|
+
if (CATPPUCCIN_FLAVOR_VALUES.includes(preference)) return;
|
|
2058
|
+
try {
|
|
2059
|
+
localStorage.setItem(RESTORE_STORAGE_KEY, preference);
|
|
2060
|
+
} catch {}
|
|
2061
|
+
}
|
|
2062
|
+
/** The preference to restore when turning the flavour off (default: system). */
|
|
2063
|
+
function readRestoredPreference() {
|
|
2064
|
+
try {
|
|
2065
|
+
const raw = localStorage.getItem(RESTORE_STORAGE_KEY);
|
|
2066
|
+
return raw === "light" || raw === "dark" ? raw : "system";
|
|
2067
|
+
} catch {
|
|
2068
|
+
return "system";
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
1984
2071
|
/** Required services: slots + locale (settings rows) and theme (register + switch). */
|
|
1985
2072
|
const inject = [
|
|
1986
2073
|
"slots",
|
|
@@ -2023,6 +2110,7 @@ window.__ModuleLoader__.load({
|
|
|
2023
2110
|
});
|
|
2024
2111
|
ctx.effect(() => {
|
|
2025
2112
|
const applyDesired = () => {
|
|
2113
|
+
rememberBuiltinPreference(theme.getTheme().preference);
|
|
2026
2114
|
const desired = readFlavor();
|
|
2027
2115
|
if (desired === "off") return;
|
|
2028
2116
|
const preference = theme.getTheme().preference;
|
|
@@ -2079,7 +2167,7 @@ window.__ModuleLoader__.load({
|
|
|
2079
2167
|
select: (choice) => {
|
|
2080
2168
|
if (choice === "off") {
|
|
2081
2169
|
writeFlavor("off");
|
|
2082
|
-
theme.setTheme(
|
|
2170
|
+
theme.setTheme(readRestoredPreference());
|
|
2083
2171
|
scheduleDurablePersist(buildLocalState);
|
|
2084
2172
|
return;
|
|
2085
2173
|
}
|
|
@@ -2149,11 +2237,14 @@ window.__ModuleLoader__.load({
|
|
|
2149
2237
|
exports.CATPPUCCIN_FLAVOR_VALUES = CATPPUCCIN_FLAVOR_VALUES;
|
|
2150
2238
|
exports.FLAVOR_STORAGE_KEY = FLAVOR_STORAGE_KEY;
|
|
2151
2239
|
exports.NS = NS;
|
|
2240
|
+
exports.RESTORE_STORAGE_KEY = RESTORE_STORAGE_KEY;
|
|
2152
2241
|
exports.apply = apply;
|
|
2153
2242
|
exports.flavorFromThemeId = flavorFromThemeId;
|
|
2154
2243
|
exports.flavorInfo = flavorInfo;
|
|
2155
2244
|
exports.inject = inject;
|
|
2156
2245
|
exports.readFlavor = readFlavor;
|
|
2246
|
+
exports.readRestoredPreference = readRestoredPreference;
|
|
2247
|
+
exports.rememberBuiltinPreference = rememberBuiltinPreference;
|
|
2157
2248
|
exports.writeFlavor = writeFlavor;
|
|
2158
2249
|
return module.exports;
|
|
2159
2250
|
}
|