From 4a923eaf01a69173581613700f88d27318d5e289 Mon Sep 17 00:00:00 2001 From: Sandro Date: Sat, 31 Oct 2026 10:12:55 +0100 Subject: [PATCH] feat(pwa): loading screen in the colours of the last used theme Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 ++ frontend/index.html | 26 +++++++++++++++++++++----- frontend/public/boot-theme.js | 17 +++++++++++++++++ frontend/public/sw.js | 4 +++- frontend/src/lib/theme.ts | 10 +++++++++- 5 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 frontend/public/boot-theme.js diff --git a/CHANGELOG.md b/CHANGELOG.md index c678126..1040f15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V ### Changed - Kanban maximieren: Nur noch das Board wird breiter, Listen-Reiter und „Neue Aufgabe anlegen“ behalten ihre Breite. Das Board wächst weich animiert, jede Spalte wird höchstens 380 px breit und das Board bleibt mittig (bei wenigen Spalten also schmaler als das Fenster). +- Ladebildschirm: Statt immer in Blau erscheint er in den Farben des zuletzt auf dem Gerät genutzten Themes (Hintergrund, Logo in der Akzentfarbe, Statusleiste passend); beim allerersten Besuch bleibt er blau. Neu dafür ist `boot-theme.js` (eigene Datei wegen der Content-Security-Policy); die App-Caches werden einmal erneuert. + ### Fixed - App installieren am Handy: Meldet Chrome erst nach dem Öffnen der Anleitung, dass MindSift installierbar ist (z. B. kurz nach dem Entfernen der alten App), erscheint in der Anleitung jetzt ein Knopf „Jetzt installieren“ für die direkte Installation. diff --git a/frontend/index.html b/frontend/index.html index 3a81e97..97e492a 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,8 +3,10 @@ - + + @@ -43,11 +45,25 @@ - +
-
- - +
+ + + + + + + + + + + + + + +
diff --git a/frontend/public/boot-theme.js b/frontend/public/boot-theme.js new file mode 100644 index 0000000..ad962a1 --- /dev/null +++ b/frontend/public/boot-theme.js @@ -0,0 +1,17 @@ +// Runs before the first paint: the loading screen takes the colours of the theme used last on this +// device (stored by the app in lib/theme.ts), so a light or orange theme does not start in blue. +// A file instead of an inline script so the CSP can stay at script-src 'self'. +(function () { + try { + var colors = JSON.parse(localStorage.getItem('mindsift_boot_colors') || 'null'); + if (!colors || typeof colors.bg !== 'string' || typeof colors.accent !== 'string') return; + var root = document.documentElement; + root.style.setProperty('--boot-bg', colors.bg); + root.style.setProperty('--boot-accent', colors.accent); + if (typeof colors.onAccent === 'string') root.style.setProperty('--boot-on-accent', colors.onAccent); + var meta = document.querySelector('meta[name="theme-color"]'); + if (meta) meta.setAttribute('content', colors.bg); + } catch (e) { + // no storage: the loading screen stays blue + } +})(); diff --git a/frontend/public/sw.js b/frontend/public/sw.js index 23ecc51..551a400 100644 --- a/frontend/public/sw.js +++ b/frontend/public/sw.js @@ -7,7 +7,7 @@ // would hand it the old values), the cache only offline. // - API requests are never touched; offline data comes from the app's own cache (lib/offline.ts). // Raise VERSION when this file changes in a way that needs fresh caches. -const VERSION = 'v5'; +const VERSION = 'v6'; const SHELL_CACHE = `mindsift-shell-${VERSION}`; const ASSET_CACHE = `mindsift-assets-${VERSION}`; const MAX_ASSETS = 80; @@ -23,6 +23,8 @@ const SHELL_URLS = [ '/icon-512x512.png', '/apple-touch-icon.png', '/badge-96x96.png', + '/boot-theme.js', + '/pwa-install.js', ]; self.addEventListener('install', (event) => { diff --git a/frontend/src/lib/theme.ts b/frontend/src/lib/theme.ts index 3a08ec0..b594469 100644 --- a/frontend/src/lib/theme.ts +++ b/frontend/src/lib/theme.ts @@ -236,6 +236,7 @@ export function getAccentColor(): string | null { export function setAccentColor(hex: string | null): void { store(ACCENT_KEY, hex); applyAccent(hex); + syncThemeColorMeta(); // keeps the loading screen's colours current } function hexToRgb(hex: string): [number, number, number] { @@ -352,15 +353,22 @@ function applyToDocument(themeId: ThemeId, customCss: string | null): void { // The status bar (theme-color) starts black (like the Android navigation bar of the installed app, // which only takes the manifest colour); once the app runs it follows the theme's background. +// The colours are also kept for the next start: public/boot-theme.js paints the loading screen in them. function syncThemeColorMeta(): void { const meta = document.querySelector('meta[name="theme-color"]'); if (!meta || typeof requestAnimationFrame === 'undefined') return; requestAnimationFrame(() => { - const bg = getComputedStyle(document.documentElement).getPropertyValue('--bg-app').trim(); + const css = getComputedStyle(document.documentElement); + const bg = css.getPropertyValue('--bg-app').trim(); if (bg) meta.setAttribute('content', bg); + const accent = css.getPropertyValue('--accent-primary').trim(); + const onAccent = css.getPropertyValue('--text-on-accent').trim(); + if (bg && accent) store(BOOT_COLORS_KEY, JSON.stringify({ bg, accent, onAccent })); }); } +const BOOT_COLORS_KEY = 'mindsift_boot_colors'; + function store(key: string, value: string | null): void { try { if (value === null) localStorage.removeItem(key);