Colour theme is configurable at runtime from two seed colours (brand + accent); neutrals stay fixed for contrast safety. Tailwind v4 var()-based tokens let a :root:root override recolour everything with no rebuild; the 50->950 ramps are derived via a color-mix ladder. Config lives in the DB config table (admin UI: Config > Farbschema, presets + custom pickers + live preview), served on the public /event endpoint with env defaults (THEME_PRESET/PRIMARY/ACCENT), propagated live via event-updated SSE, and cached in localStorage for a no-flash boot. The keepsake export mirrors the same ladder in Rust so offline archives match the event theme. COMMENTS_ENABLED (env, default true) is a boot-time kill-switch: the backend rejects new comments with 403 and the frontend hides the comment button (feed card) and panel/composer (lightbox). Existing comments stay in the DB, hidden, and return when re-enabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
/**
|
|
* Public event presentation config: the colour theme and the comments feature flag,
|
|
* served unauthenticated from `GET /api/v1/event`. Loaded once on boot (and refreshed
|
|
* on the `event-updated` SSE) so the theme applies before the user has even joined and
|
|
* the comment UI reflects the instance setting.
|
|
*
|
|
* The resolved theme CSS is cached in localStorage so the boot script in app.html can
|
|
* paint the right colours before the JS bundle loads (no flash of the default palette).
|
|
*/
|
|
import { writable } from 'svelte/store';
|
|
import { buildPaletteCss, applyPaletteCss, type ThemeConfig } from './theme/palette';
|
|
|
|
export const PALETTE_CACHE_KEY = 'eventsnap_palette_css';
|
|
|
|
export type EventConfig = {
|
|
name: string;
|
|
slug: string;
|
|
commentsEnabled: boolean;
|
|
theme: ThemeConfig;
|
|
};
|
|
|
|
export const eventConfig = writable<EventConfig | null>(null);
|
|
/** Convenience flag for the comment UI. Optimistic `true` until /event resolves. */
|
|
export const commentsEnabled = writable<boolean>(true);
|
|
|
|
/** Fetch /event, apply the theme, and cache the resolved CSS for the next boot. */
|
|
export async function loadEventConfig(): Promise<void> {
|
|
try {
|
|
const res = await fetch('/api/v1/event');
|
|
if (!res.ok) return;
|
|
const b = await res.json();
|
|
const theme: ThemeConfig = {
|
|
preset: b.theme_preset ?? 'champagne-gold',
|
|
primary: b.theme_primary ?? '#8a6a2b',
|
|
accent: b.theme_accent ?? '#8a6a2b'
|
|
};
|
|
eventConfig.set({
|
|
name: b.name,
|
|
slug: b.slug,
|
|
commentsEnabled: b.comments_enabled ?? true,
|
|
theme
|
|
});
|
|
commentsEnabled.set(b.comments_enabled ?? true);
|
|
|
|
const css = buildPaletteCss(theme);
|
|
applyPaletteCss(css);
|
|
try {
|
|
localStorage.setItem(PALETTE_CACHE_KEY, css);
|
|
} catch {
|
|
/* private mode / quota — the theme still applied for this session */
|
|
}
|
|
} catch {
|
|
/* offline / server down — keep whatever the boot script already painted */
|
|
}
|
|
}
|
|
|
|
/** Apply a theme immediately without persisting — used by the admin live preview. */
|
|
export function previewTheme(theme: ThemeConfig): void {
|
|
applyPaletteCss(buildPaletteCss(theme));
|
|
}
|