Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
149 lines (146 loc) Β· 6.37 KB
/
Copy pathindex.html
File metadata and controls
149 lines (146 loc) Β· 6.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WaveFlow</title>
</head>
<body>
<!--
Theme bootstrap β paints the right mode (dark class + data-theme +
ambient background) before React mounts so a fresh boot doesn't
flash white when the default theme is dark. Keeps it minimal: only
the dark class + ambient color need to be right on the first paint;
the full accent palette is hydrated by `ThemeProvider`'s effect a
few ms later, which is invisible against an already-correct bg.
Mirrors `themes.ts` β `LIGHT_IDS` lists every light preset (6),
everything else is dark (8). Keep the two tables in sync if a
preset is added / removed.
-->
<script>
(function () {
var root = document.documentElement;
// WebKitGTK can retain very large compositing surfaces for the
// glass-heavy Lounge and Liquid skins. Set the safeguard before
// reading storage so a remembered skin is safe on its first paint.
// Exclude other Linux browsers used for frontend development.
var ua = navigator.userAgent;
if (
/linux/i.test(ua) &&
/AppleWebKit/i.test(ua) &&
!/(Chrome|Chromium|Edg|Android)/i.test(ua)
) {
root.setAttribute("data-webkitgtk-safe", "");
}
try {
var id =
localStorage.getItem("waveflow.theme.id") ||
(localStorage.getItem("waveflow.theme.is_dark") === "false"
? "default"
: "default-dark");
var LIGHT_IDS = {
default: 1,
"midnight-light": 1,
"sunset-light": 1,
"lavender-light": 1,
"crimson-light": 1,
"ocean-light": 1,
};
var ambient =
{
default: "#ffffff",
"midnight-light": "#e0e7ff",
"sunset-light": "#fef3c7",
"lavender-light": "#ede9fe",
"crimson-light": "#ffe4e6",
"ocean-light": "#e0f2fe",
"default-dark": "#121212",
oled: "#000000",
midnight: "#0b1020",
sunset: "#1a0e08",
lavender: "#15101e",
crimson: "#19090c",
ocean: "#081420",
neon: "#1a0a18",
}[id] || "#121212";
root.setAttribute("data-theme", id);
root.style.setProperty("--ambient-bg", ambient);
if (!LIGHT_IDS[id]) root.classList.add("dark");
// Skin bootstrap β paint the right `data-skin` before
// React mounts so font / radius / density tokens used
// by the very first paint surfaces (sidebar, topbar)
// don't flicker from the default Studio metrics to
// Editorial on hydration. The full skin tokens are
// hydrated by `SkinProvider`'s effect a few ms later;
// only the attribute needs to be right on first paint
// because `@theme inline` in app.css resolves the
// attribute-selector overrides synchronously with the
// first CSS pass.
//
// Whitelist the stored id so an obsolete or garbage
// value can't land on `data-skin` and silently break
// every `[data-skin="<known>"]` rule. Must stay in
// sync with `SKIN_PRESETS` in `src/lib/skins.ts`.
var VALID_SKINS = {
studio: 1,
editorial: 1,
lounge: 1,
pulse: 1,
liquid: 1,
fluid: 1,
};
// The native startup path adds this flag before creating the
// webview. It must beat the cached skin on the very first paint.
var skin =
new URLSearchParams(location.search).get("safe-mode") === "1"
? "studio"
: localStorage.getItem("waveflow.skin.id");
// Nothing cached (a first launch, a cleared store): the
// default skin, which the context will confirm from the profile.
if (!skin || !VALID_SKINS[skin]) skin = "fluid";
root.setAttribute("data-skin", skin);
// Contrast bootstrap (#596) β stamp `data-contrast` before
// React mounts. This matters more than the theme's own
// bootstrap does: a flash of low-contrast chrome is exactly
// what the person who turned this on cannot read.
//
// `auto` (the default) defers to the OS, so the attribute
// carries the RESOLVED state, never the stored choice β the
// stylesheet keys on "high" / "normal" and must not have to
// know what `auto` resolved to. `ContrastProvider` re-stamps
// it a few ms later from the database row, which is what
// corrects a stale cache after a profile switch.
var contrast = localStorage.getItem("waveflow.contrast");
if (contrast !== "high" && contrast !== "normal") contrast = "auto";
var high =
contrast === "high" ||
(contrast === "auto" &&
window.matchMedia &&
window.matchMedia("(prefers-contrast: more)").matches);
root.setAttribute("data-contrast", high ? "high" : "normal");
// Accent bootstrap -- the scale last applied, whether it came
// from the theme, a picked colour or a cover. Without it the
// first frame shows the stylesheet's green until React applies
// the real one. Only plain `oklch(...)` values are let through:
// this writes straight into the root's style.
var cachedAccent = JSON.parse(
localStorage.getItem("waveflow.accent.scale") || "null",
);
var stops = cachedAccent && cachedAccent.stops;
var SHADES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
if (Array.isArray(stops) && stops.length === SHADES.length) {
for (var i = 0; i < SHADES.length; i++) {
if (/^oklch\([0-9. ]+\)$/.test(stops[i])) {
root.style.setProperty("--accent-" + SHADES[i], stops[i]);
}
}
}
} catch (_) {
// localStorage unavailable β fall through to :root defaults.
}
})();
</script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>