Files
picpeak/frontend/index.html
T
Paul Nothaft f81a8728e6 fix(theme): pre-React bootstrap to kill white-flash on dark galleries (#358)
Opening a gallery with a dark theme briefly painted a white background
between the initial HTML render and React applying the per-event theme.
The HTML shipped with no theme info, so the first paint used the
default (#fafafa) before /gallery/:slug/info resolved.

Two-part fix.

1. Inline bootstrap script in index.html runs synchronously before React
   mounts. Reads the URL, looks up a per-slug background colour from
   localStorage (gallery-theme-bg-<slug>), and applies it to
   documentElement immediately. Falls back to #171717 when no cache
   exists and the OS prefers dark, so first visits with dark OS still
   land on a dark background.

2. ThemeContext.applyTheme writes the resolved background to
   localStorage keyed by slug whenever a gallery theme loads. Revisits
   then hit the bootstrap cache and never see a flash.

Added a 200ms transition on html.background-color so the rare
cache→API drift (e.g. theme palette changed admin-side since last
visit) is a smooth fade instead of a snap.

Limitation: first visit on a light-OS device to a dark gallery still
flashes once. Killing that case requires a server-rendered theme hint,
out of scope for an SPA bootstrap fix.

The empty-skeleton-grid part of the same report is already addressed
by the 300ms lazy render in #352 — Rekoo-PS just needs to update from
v3.32.1-beta.0 to v3.32.2-beta.0+.
2026-05-01 23:53:55 +02:00

51 lines
1.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<title>PicPeak - Photo Sharing Platform</title>
<script>
/*
* Pre-React theme bootstrap (#358).
*
* Without this, opening a dark-themed gallery flashes a white
* background between the HTML paint and React applying the gallery
* theme. We resolve a background colour synchronously from the URL
* slug (cached on previous visits) or the OS preference, and apply
* it to documentElement before any React render runs.
*
* Per-gallery cache is written by ThemeContext when the gallery
* theme actually loads, keyed by slug, so revisits never flash.
* First visits with no cache fall back to the OS preference.
*/
(function () {
try {
var m = location.pathname.match(/\/gallery\/([^\/?#]+)/);
var bg = null;
if (m && m[1]) {
bg = localStorage.getItem('gallery-theme-bg-' + decodeURIComponent(m[1]));
}
if (!bg && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
bg = '#171717';
}
if (bg) {
var root = document.documentElement;
root.style.backgroundColor = bg;
root.style.setProperty('--color-background', bg);
}
} catch (e) { /* never block render on a cache miss */ }
})();
</script>
<style>
/* Smooth out the cache→API theme transition for the rare case where
the cached colour drifts from the freshly fetched theme (#358). */
html { transition: background-color 200ms ease; }
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>