feat(pwa): loading screen in the colours of the last used theme
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
57a97a3750
commit
4a923eaf01
5 files changed
+52
-7
No files matched your search
+21
-5
@@ -3,8 +3,10 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<!-- Blue while loading (matches the splash screen); the app switches it to the theme background -->
|
||||
<!-- Black like the system bars of the installed app; boot-theme.js and then the app switch it to the
|
||||
theme background -->
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<script src="/boot-theme.js"></script>
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="MindSift" />
|
||||
@@ -43,11 +45,25 @@
|
||||
<script src="/pwa-install.js"></script>
|
||||
</head>
|
||||
<body class="bg-[#0b0f19] text-[#e3e3e3] antialiased selection:bg-[#8ab4f8]/30 selection:text-[#8ab4f8]">
|
||||
<!-- Shown until React mounts and replaces it: full blue with the logo, no text, no white flash -->
|
||||
<!-- Shown until React mounts and replaces it: the logo on the background of the theme used last on
|
||||
this device (boot-theme.js), full blue on the first visit; no text, no white flash -->
|
||||
<div id="root">
|
||||
<div style="position:fixed;inset:0;background:#2563eb;display:flex;align-items:center;justify-content:center">
|
||||
<!-- the icon's own blue square disappears on blue, so the visible brain is ~55% of this size -->
|
||||
<img src="/icon.svg" width="128" height="128" alt="" style="display:block" />
|
||||
<div style="position:fixed;inset:0;background:var(--boot-bg,#2563eb);display:flex;align-items:center;justify-content:center">
|
||||
<!-- icon.svg inline, so its square takes the theme's accent (on blue it disappears in the background) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="128" height="128" style="display:block">
|
||||
<rect width="512" height="512" rx="108" style="fill:var(--boot-accent,#2563eb)" />
|
||||
<g transform="translate(256, 256) scale(12.5) translate(-12, -12)" fill="none" style="stroke:var(--boot-on-accent,#ffffff)" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/>
|
||||
<path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/>
|
||||
<path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/>
|
||||
<path d="M17.599 6.5a3 3 0 0 0 .399-1.375"/>
|
||||
<path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"/>
|
||||
<path d="M3.477 10.896a4 4 0 0 1 .585-.396"/>
|
||||
<path d="M19.938 10.5a4 4 0 0 1 .585.396"/>
|
||||
<path d="M6 18a4 4 0 0 1-1.967-.516"/>
|
||||
<path d="M19.967 17.484A4 4 0 0 1 18 18"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})();
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user