From bcaedbab5c2648672606d912dad5dcf68b3fb405 Mon Sep 17 00:00:00 2001 From: nmemmert <67961292+nmemmert@users.noreply.github.com> Date: Tue, 27 Oct 2026 09:50:23 -0400 Subject: [PATCH] Themes: accent colours and AMOLED black per person Co-Authored-By: Claude Sonnet 5.5 --- public/boot.js | 1 + public/themes.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 public/themes.js diff --git a/public/boot.js b/public/boot.js index a24746c..e9983df 100644 --- a/public/boot.js +++ b/public/boot.js @@ -18,6 +18,7 @@ setInterval(checkForUpdate, 10 * 60e3); await loadMe(); await loadSettings(); + if (typeof themeStart === 'function') themeStart(); sgStart(); if (typeof chStart === 'function') chStart(); if (typeof kidStart === 'function') kidStart(); if (typeof devStart === 'function') devStart(); if (typeof simpleStart === 'function') simpleStart(); addEventListener('hashchange', route); restorePlayer(); diff --git a/public/themes.js b/public/themes.js new file mode 100644 index 0000000..e6d096b --- /dev/null +++ b/public/themes.js @@ -0,0 +1,32 @@ +'use strict'; +// ---- Themes: each person picks an accent colour and Auto, Light, Dark or AMOLED black (true black, easy on phone batteries). Kept in their synced settings, so it follows them between devices. +const THEME_ACCENTS = [['blue', 'Blue', '#3d6bf0', '#6a8cff'], ['teal', 'Teal', '#0f8f8a', '#3cc7c0'], ['green', 'Green', '#2f9e6e', '#4cc98d'], ['orange', 'Orange', '#d9741a', '#f09a45'], ['red', 'Red', '#d4392f', '#ff6b60'], ['pink', 'Pink', '#c9407d', '#f26aa4'], ['purple', 'Purple', '#7b4fe0', '#a688ff']]; +const THEME_MODES = [['auto', 'Auto'], ['light', 'Light'], ['dark', 'Dark'], ['amoled', 'AMOLED']]; +const THEME_VARS = { + light: { '--bg': '#f5f6f8', '--panel': '#fff', '--panel2': '#eef0f4', '--text': '#14171c', '--muted': '#6a7280', '--line': '#e0e3e9' }, + dark: { '--bg': '#0f1115', '--panel': '#181b21', '--panel2': '#20242c', '--text': '#eceef2', '--muted': '#8b93a3', '--line': '#272c35' }, + amoled: { '--bg': '#000', '--panel': '#0b0b0d', '--panel2': '#16171b', '--text': '#eceef2', '--muted': '#8b93a3', '--line': '#1f2127' }, +}; +function themeApply() { + const root = document.documentElement, mode = store.get('theme_mode', 'auto'), acc = THEME_ACCENTS.find(a => a[0] === store.get('theme_accent', 'blue')) || THEME_ACCENTS[0]; + const dark = mode === 'dark' || mode === 'amoled' || (mode === 'auto' && matchMedia('(prefers-color-scheme: dark)').matches); + for (const k of Object.keys(THEME_VARS.light)) { if (mode === 'auto') root.style.removeProperty(k); else root.style.setProperty(k, THEME_VARS[mode][k]); } + const hex = dark ? acc[3] : acc[2]; + if (acc[0] === 'blue' && mode === 'auto') { root.style.removeProperty('--accent'); root.style.removeProperty('--accent-t'); } + else { const n = parseInt(hex.slice(1), 16), lum = (0.299 * (n >> 16) + 0.587 * ((n >> 8) & 255) + 0.114 * (n & 255)) / 255; root.style.setProperty('--accent', hex); root.style.setProperty('--accent-t', lum > .6 ? '#0b1020' : '#fff'); } + root.style.colorScheme = mode === 'auto' ? '' : dark ? 'dark' : 'light'; + const m = document.querySelector('meta[name=theme-color]'); if (m) m.content = dark ? (mode === 'amoled' ? '#000000' : '#0f1115') : (mode === 'light' ? '#f5f6f8' : m.content); +} +function themeStart() { themeApply(); try { matchMedia('(prefers-color-scheme: dark)').addEventListener('change', themeApply); } catch {} } +function themeSettings(el) { + if (!el) return; + const draw = () => { + const mode = store.get('theme_mode', 'auto'), acc = store.get('theme_accent', 'blue'); + el.innerHTML = `

Look

Saved for you and used on every device you sign in on.

+
${THEME_MODES.map(([k, l]) => `${l}`).join('')}
+
${THEME_ACCENTS.map(([k, l, c]) => ``).join('')}
`; + el.querySelectorAll('[data-m]').forEach(a => a.onclick = e => { e.preventDefault(); store.set('theme_mode', a.dataset.m); themeApply(); draw(); }); + el.querySelectorAll('[data-a]').forEach(b => b.onclick = () => { store.set('theme_accent', b.dataset.a); themeApply(); draw(); }); + }; + draw(); +}