pass theme as context
This commit is contained in:
parent
ba56edf588
commit
8f497cae85
|
@ -8,20 +8,21 @@ import Scoreboard from './Scoreboard.tsx';
|
||||||
import Button from './components/Button.tsx';
|
import Button from './components/Button.tsx';
|
||||||
import MapChooser from './MapChooser.tsx';
|
import MapChooser from './MapChooser.tsx';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import {getRandomTheme, useStoredTheme} from './theme.ts';
|
import {ThemeContext, getRandomTheme, useStoredTheme} from './theme.ts';
|
||||||
import {useState} from 'react';
|
import {useState} from 'react';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [theme, setTheme] = useStoredTheme();
|
const [theme, setTheme] = useStoredTheme();
|
||||||
const [name, setName] = useState<string | null>(null);
|
const [name, setName] = useState<string | null>(null);
|
||||||
|
|
||||||
return <Column className="flex-grow">
|
return <ThemeContext.Provider value={theme}>
|
||||||
|
<Column className="flex-grow">
|
||||||
|
|
||||||
<ClientScreen theme={theme} player={name}/>
|
<ClientScreen player={name}/>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<h1 className="flex-grow">CCCB-Tanks!</h1>
|
<h1 className="flex-grow">CCCB-Tanks!</h1>
|
||||||
<MapChooser theme={theme}/>
|
<MapChooser />
|
||||||
<Button text="☼ change colors" onClick={() => setTheme(_ => getRandomTheme())}/>
|
<Button text="☼ change colors" onClick={() => setTheme(_ => getRandomTheme())}/>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => window.open('https://github.com/kaesaecracker/cccb-tanks-cs', '_blank')?.focus()}
|
onClick={() => window.open('https://github.com/kaesaecracker/cccb-tanks-cs', '_blank')?.focus()}
|
||||||
|
@ -38,5 +39,6 @@ export default function App() {
|
||||||
<Scoreboard/>
|
<Scoreboard/>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
</Column>;
|
</Column>
|
||||||
|
</ThemeContext.Provider>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import {Theme} from './theme.ts';
|
|
||||||
import {makeApiUrl, useMyWebSocket} from './serverCalls.tsx';
|
import {makeApiUrl, useMyWebSocket} from './serverCalls.tsx';
|
||||||
import {ReadyState} from 'react-use-websocket';
|
import {ReadyState} from 'react-use-websocket';
|
||||||
import PixelGridCanvas from './components/PixelGridCanvas.tsx';
|
import PixelGridCanvas from './components/PixelGridCanvas.tsx';
|
||||||
|
|
||||||
|
|
||||||
export default function ClientScreen({theme, player}: {
|
export default function ClientScreen({player}: {
|
||||||
theme: Theme,
|
|
||||||
player: string | null
|
player: string | null
|
||||||
}) {
|
}) {
|
||||||
const [shouldSendMessage, setShouldSendMessage] = useState(false);
|
const [shouldSendMessage, setShouldSendMessage] = useState(false);
|
||||||
|
@ -40,5 +38,5 @@ export default function ClientScreen({theme, player}: {
|
||||||
return <></>;
|
return <></>;
|
||||||
|
|
||||||
const pixels = new Uint8ClampedArray(lastMessage.data);
|
const pixels = new Uint8ClampedArray(lastMessage.data);
|
||||||
return <PixelGridCanvas pixels={pixels} theme={theme}/>;
|
return <PixelGridCanvas pixels={pixels}/>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import {makeApiUrl, MapInfo} from './serverCalls';
|
||||||
import Dialog from './components/Dialog.tsx';
|
import Dialog from './components/Dialog.tsx';
|
||||||
import PixelGridCanvas from './components/PixelGridCanvas.tsx';
|
import PixelGridCanvas from './components/PixelGridCanvas.tsx';
|
||||||
import Column from './components/Column.tsx';
|
import Column from './components/Column.tsx';
|
||||||
import {Theme} from './theme.ts';
|
|
||||||
import Button from './components/Button.tsx';
|
import Button from './components/Button.tsx';
|
||||||
import Row from './components/Row.tsx';
|
import Row from './components/Row.tsx';
|
||||||
import './MapChooser.css';
|
import './MapChooser.css';
|
||||||
|
@ -18,9 +17,8 @@ function base64ToArrayBuffer(base64: string) {
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MapPreview({mapName, theme, highlight, onClick}: {
|
function MapPreview({mapName, highlight, onClick}: {
|
||||||
readonly mapName: string,
|
readonly mapName: string,
|
||||||
readonly theme: Theme,
|
|
||||||
readonly highlight: boolean,
|
readonly highlight: boolean,
|
||||||
readonly onClick: () => void
|
readonly onClick: () => void
|
||||||
}) {
|
}) {
|
||||||
|
@ -47,15 +45,14 @@ function MapPreview({mapName, theme, highlight, onClick}: {
|
||||||
className={'MapChooser-Preview' + (highlight ? ' MapChooser-Preview-Highlight' : '')}
|
className={'MapChooser-Preview' + (highlight ? ' MapChooser-Preview-Highlight' : '')}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<PixelGridCanvas pixels={base64ToArrayBuffer(preview)} theme={theme}/>
|
<PixelGridCanvas pixels={base64ToArrayBuffer(preview)}/>
|
||||||
<p>{name}</p>
|
<p>{name}</p>
|
||||||
</Column>;
|
</Column>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function MapChooserDialog({mapNames, theme, onClose, onConfirm}: {
|
function MapChooserDialog({mapNames, onClose, onConfirm}: {
|
||||||
readonly mapNames: string[];
|
readonly mapNames: string[];
|
||||||
readonly theme: Theme;
|
|
||||||
readonly onConfirm: (mapName: string) => void;
|
readonly onConfirm: (mapName: string) => void;
|
||||||
readonly onClose: () => void;
|
readonly onClose: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
@ -66,22 +63,19 @@ function MapChooserDialog({mapNames, theme, onClose, onConfirm}: {
|
||||||
{mapNames.map(name => <MapPreview
|
{mapNames.map(name => <MapPreview
|
||||||
key={name}
|
key={name}
|
||||||
mapName={name}
|
mapName={name}
|
||||||
theme={theme}
|
|
||||||
highlight={chosenMap == name}
|
highlight={chosenMap == name}
|
||||||
onClick={() => setChosenMap(name)}
|
onClick={() => setChosenMap(name)}
|
||||||
/>)}
|
/>)}
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<div className='flex-grow'/>
|
<div className="flex-grow"/>
|
||||||
<Button text="« cancel" onClick={onClose}/>
|
<Button text="« cancel" onClick={onClose}/>
|
||||||
<Button text="√ confirm" disabled={!chosenMap} onClick={() => chosenMap && onConfirm(chosenMap)}/>
|
<Button text="√ confirm" disabled={!chosenMap} onClick={() => chosenMap && onConfirm(chosenMap)}/>
|
||||||
</Row>
|
</Row>
|
||||||
</Dialog>;
|
</Dialog>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MapChooser({theme}: {
|
export default function MapChooser({}: {}) {
|
||||||
readonly theme: Theme;
|
|
||||||
}) {
|
|
||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: ['get-maps'],
|
queryKey: ['get-maps'],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
@ -114,7 +108,6 @@ export default function MapChooser({theme}: {
|
||||||
{query.isSuccess && open &&
|
{query.isSuccess && open &&
|
||||||
<MapChooserDialog
|
<MapChooserDialog
|
||||||
mapNames={query.data!}
|
mapNames={query.data!}
|
||||||
theme={theme}
|
|
||||||
onClose={() => setOpen(false)}
|
onClose={() => setOpen(false)}
|
||||||
onConfirm={name => {
|
onConfirm={name => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {hslToString, Theme} from '../theme.ts';
|
import {hslToString, ThemeContext} from '../theme.ts';
|
||||||
import {useEffect, useRef} from 'react';
|
import {useContext, useEffect, useRef} from 'react';
|
||||||
import './PixelGridCanvas.css';
|
import './PixelGridCanvas.css';
|
||||||
|
|
||||||
const pixelsPerRow = 352;
|
const pixelsPerRow = 352;
|
||||||
|
@ -104,10 +104,10 @@ function drawPixelsToCanvas(
|
||||||
context.putImageData(imageData, 0, 0);
|
context.putImageData(imageData, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PixelGridCanvas({pixels, theme}: {
|
export default function PixelGridCanvas({pixels}: {
|
||||||
readonly pixels: Uint8ClampedArray;
|
readonly pixels: Uint8ClampedArray;
|
||||||
readonly theme: Theme;
|
|
||||||
}) {
|
}) {
|
||||||
|
const theme = useContext(ThemeContext);
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {useStoredObjectState} from "./useStoredState.ts";
|
import {useStoredObjectState} from './useStoredState.ts';
|
||||||
|
import {createContext} from 'react';
|
||||||
|
|
||||||
export type Theme = {
|
export type Theme = {
|
||||||
primary: HSL;
|
primary: HSL;
|
||||||
|
@ -88,3 +89,5 @@ export function useStoredTheme() {
|
||||||
save: applyTheme
|
save: applyTheme
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ThemeContext = createContext<Theme>(getRandomTheme());
|
||||||
|
|
Loading…
Reference in a new issue