translations and pickers

This commit is contained in:
Mateusz Gruszczyński
2026-09-05 08:56:45 +02:00
parent e68ad69bc5
commit bf34a7cab1
18 changed files with 606 additions and 63 deletions
+48 -8
View File
@@ -7,6 +7,8 @@
* See LICENSE file in repository root for details.
*/
const STORAGE_KEY = "rustpad:theme";
const GUEST_STORAGE_KEY = "rustpad:guest-theme";
const AUTH_STATE_KEY = "rustpad:auth-state";
const THEMES = new Set(["dark", "light"]);
const systemThemeQuery = window.matchMedia("(prefers-color-scheme: light)");
@@ -28,31 +30,69 @@ export function getTheme() {
return normalizeTheme(document.documentElement.dataset.theme);
}
export function applyTheme(value, { persist = true } = {}) {
function hasAccountSession() {
try { return localStorage.getItem(AUTH_STATE_KEY) === "1"; } catch { return false; }
}
function persistTheme(theme, scope = "auto") {
try {
localStorage.setItem(STORAGE_KEY, theme);
const guestScope = scope === "guest" || (scope === "auto" && !hasAccountSession());
if (guestScope) localStorage.setItem(GUEST_STORAGE_KEY, theme);
} catch { }
}
export function applyTheme(value, { persist = true, scope = "auto" } = {}) {
const theme = normalizeTheme(value);
const previousTheme = getTheme();
updateBrowserChrome(theme);
if (persist) {
try { localStorage.setItem(STORAGE_KEY, theme); } catch { }
}
if (persist) persistTheme(theme, scope);
if (theme !== previousTheme) {
window.dispatchEvent(new CustomEvent("rustpad:theme-change", { detail: { theme } }));
}
return theme;
}
export function rememberGuestTheme(value = getTheme()) {
try {
if (THEMES.has(localStorage.getItem(GUEST_STORAGE_KEY))) return;
localStorage.setItem(GUEST_STORAGE_KEY, normalizeTheme(value));
} catch { }
}
export function restoreGuestTheme() {
let saved = null;
try { saved = localStorage.getItem(GUEST_STORAGE_KEY); } catch { }
if (THEMES.has(saved)) {
try { localStorage.setItem(STORAGE_KEY, saved); } catch { }
return applyTheme(saved, { persist: false });
}
try { localStorage.removeItem(STORAGE_KEY); } catch { }
return applyTheme(systemTheme(), { persist: false });
}
export function applySessionTheme(session) {
if (session?.theme) applyTheme(session.theme);
if (session?.theme) applyTheme(session.theme, { scope: "account" });
}
window.addEventListener("storage", event => {
if (event.key !== STORAGE_KEY) return;
applyTheme(THEMES.has(event.newValue) ? event.newValue : systemTheme(), { persist: false });
if (event.key !== STORAGE_KEY && event.key !== GUEST_STORAGE_KEY && event.key !== AUTH_STATE_KEY) return;
if (event.key === GUEST_STORAGE_KEY && hasAccountSession()) return;
let saved = null;
try {
saved = hasAccountSession()
? localStorage.getItem(STORAGE_KEY)
: (localStorage.getItem(GUEST_STORAGE_KEY) || localStorage.getItem(STORAGE_KEY));
} catch { }
applyTheme(THEMES.has(saved) ? saved : systemTheme(), { persist: false });
});
systemThemeQuery.addEventListener("change", () => {
try {
if (THEMES.has(localStorage.getItem(STORAGE_KEY))) return;
const saved = hasAccountSession()
? localStorage.getItem(STORAGE_KEY)
: (localStorage.getItem(GUEST_STORAGE_KEY) || localStorage.getItem(STORAGE_KEY));
if (THEMES.has(saved)) return;
} catch { }
applyTheme(systemTheme(), { persist: false });
});