From 4960df370ce4dd1de07d768874231bc1e5064c44 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Tue, 7 May 2024 12:28:04 +0200 Subject: [PATCH] hsl to rgba not as effect but immediately, so all components have the correct theme applied at once --- tank-frontend/src/theme.tsx | 53 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/tank-frontend/src/theme.tsx b/tank-frontend/src/theme.tsx index 0f3f8df..38a1609 100644 --- a/tank-frontend/src/theme.tsx +++ b/tank-frontend/src/theme.tsx @@ -1,5 +1,5 @@ import {useStoredObjectState} from './useStoredState.ts'; -import {createContext, ReactNode, useContext, useEffect, useRef, useState} from 'react'; +import {createContext, ReactNode, useContext, useMemo, useRef, useState} from 'react'; type HSL = { h: number; @@ -14,6 +14,15 @@ export type HslTheme = { tertiary: HSL; } +type Rgba = Uint8ClampedArray; + +export type RgbaTheme = { + primary: Rgba; + secondary: Rgba; + background: Rgba; + tertiary: Rgba; +} + // @ts-ignore const rootStyle = document.querySelector(':root')?.style; @@ -76,22 +85,6 @@ export function getRandomTheme(): HslTheme { return {background, primary, secondary, tertiary}; } -function applyTheme(theme: HslTheme) { - console.log('apply theme', theme); - rootStyle.setProperty('--color-primary', hslToString(theme.primary)); - rootStyle.setProperty('--color-secondary', hslToString(theme.secondary)); - rootStyle.setProperty('--color-background', hslToString(theme.background)); -} - -type Rgba = Uint8ClampedArray; - -export type RgbaTheme = { - primary: Rgba; - secondary: Rgba; - background: Rgba; - tertiary: Rgba; -} - const dummyRgbaTheme: RgbaTheme = { primary: new Uint8ClampedArray([0, 0, 0, 0]), secondary: new Uint8ClampedArray([0, 0, 0, 0]), @@ -105,7 +98,6 @@ function hslToRgba(context: CanvasRenderingContext2D, color: HSL) { return context.getImageData(0, 0, 1, 1).data; } - const HslThemeContext = createContext HslTheme) => void @@ -128,34 +120,41 @@ export function useHslTheme() { export function ThemeProvider({children}: { children?: ReactNode; }) { + const [rgbaTheme, setRgbaTheme] = useState(null); + + function applyTheme(theme: HslTheme) { + console.log('apply theme', theme); + rootStyle.setProperty('--color-primary', hslToString(theme.primary)); + rootStyle.setProperty('--color-secondary', hslToString(theme.secondary)); + rootStyle.setProperty('--color-background', hslToString(theme.background)); + } + const [hslTheme, setHslTheme] = useStoredObjectState('theme', getRandomTheme, { load: applyTheme, save: applyTheme }); - - const [rgbaTheme, setRgbaTheme] = useState(null); const canvasRef = useRef(null); - useEffect(() => { - const canvas = canvasRef.current; - if (canvas === null) - throw new Error('canvas null'); + const canvas = canvasRef.current; + + useMemo(() => { + if (!canvas) + return; const drawContext = canvas.getContext('2d', { - alpha: true, + alpha: false, colorSpace: 'srgb', willReadFrequently: true }); if (!drawContext) throw new Error('could not get draw context'); - setRgbaTheme({ background: hslToRgba(drawContext, hslTheme.background), primary: hslToRgba(drawContext, hslTheme.primary), secondary: hslToRgba(drawContext, hslTheme.secondary), tertiary: hslToRgba(drawContext, hslTheme.tertiary), }); - }, [hslTheme, canvasRef.current]); + }, [hslTheme, canvas]); return