import { useEffect, useRef, useState } from 'react'; import { twc } from 'react-twc'; import { createInitialPlayers } from '../../../Data/getInitialPlayers'; import { useAnalytics } from '../../../Hooks/useAnalytics'; import { useGlobalSettings } from '../../../Hooks/useGlobalSettings'; import { usePlayers } from '../../../Hooks/usePlayers'; import { Cog, Info, Trinket } from '../../../Icons/generated'; import { InitialGameSettings, Orientation, PreStartMode, defaultInitialGameSettings, } from '../../../Types/Settings'; import { baseColors } from '../../../../tailwind.config'; import { InfoDialog } from '../../Dialogs/InfoDialog'; import { SettingsDialog } from '../../Dialogs/SettingsDialog'; import { ToggleButton } from '../../Misc/ToggleButton'; import { LayoutOptions } from './LayoutOptions'; const commanderSettings: Pick< InitialGameSettings, 'numberOfPlayers' | 'startingLifeTotal' | 'orientation' > = { numberOfPlayers: 4, startingLifeTotal: 40, orientation: Orientation.Landscape, }; const standardSettings: Pick< InitialGameSettings, 'numberOfPlayers' | 'startingLifeTotal' | 'orientation' > = { numberOfPlayers: 2, startingLifeTotal: 20, orientation: Orientation.Landscape, }; const MainWrapper = twc.div`h-fit w-full pb-24 overflow-hidden items-center flex flex-col min-[349px]:pb-10`; const StartButtonFooter = twc.div`w-full max-w-[548px] fixed bottom-4 z-1 items-center flex flex-row flex-wrap px-4 z-10 gap-4`; const SliderWrapper = twc.div`mx-8 relative`; const ToggleButtonsWrapper = twc.div`flex flex-row justify-between items-center`; export const LabelText = twc.div`text-md text-text-primary font-medium`; let tracked = false; const Start = () => { const { setPlayers } = usePlayers(); const analytics = useAnalytics(); const { fullscreen, wakeLock, setShowPlay, initialGameSettings, setInitialGameSettings, settings, isPWA, setRandomizingPlayer, version, setPlaying, savedGame, saveCurrentGame, } = useGlobalSettings(); const infoDialogRef = useRef(null); const settingsDialogRef = useRef(null); const playersSliderRef = useRef(null); const healthSliderRef = useRef(null); const [playerOptions, setPlayerOptions] = useState( initialGameSettings || defaultInitialGameSettings ); // Check for new version on mount useEffect(() => { if (!tracked) { version.checkForNewVersion('start_menu'); tracked = true; } }); useEffect(() => { if (!playersSliderRef.current) { return; } let progress = 0; switch (playerOptions?.numberOfPlayers) { case 1: progress = 0; break; case 2: progress = 20; break; case 3: progress = 40; break; case 4: progress = 60; break; case 5: progress = 80; break; case 6: progress = 100; break; default: break; } playersSliderRef.current.style.background = `linear-gradient(to right, ${baseColors.secondary.main} ${progress}%, ${baseColors.secondary.dark} ${progress}%)`; }, [playerOptions?.numberOfPlayers]); useEffect(() => { if (!healthSliderRef.current) { return; } let progress = 0; switch (playerOptions?.startingLifeTotal) { case 20: progress = 0; break; case 30: progress = 25; break; case 40: progress = 50; break; case 50: progress = 75; break; case 60: progress = 100; break; default: break; } healthSliderRef.current.style.background = `linear-gradient(to right, ${baseColors.secondary.main} ${progress}%, ${baseColors.secondary.dark} ${progress}%)`; }, [playerOptions?.startingLifeTotal]); useEffect(() => { setInitialGameSettings(playerOptions); }, [playerOptions, setInitialGameSettings]); useEffect(() => { setPlayerOptions({ ...playerOptions, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [playerOptions.numberOfPlayers]); const doStartNewGame = () => { if (!initialGameSettings) { return; } analytics.trackEvent('game_started', { ...initialGameSettings, ...settings, isPWA, }); try { if (settings.goFullscreenOnStart) { fullscreen.enableFullscreen(); } } catch (error) { console.error(error); } if (settings.keepAwake && !wakeLock.active) { wakeLock.request(); } setInitialGameSettings(initialGameSettings); setPlayers(createInitialPlayers(initialGameSettings)); setRandomizingPlayer(settings.preStartMode === PreStartMode.RandomKing); setShowPlay(true); setPlaying(false); tracked = false; }; const doResumeGame = () => { if (!savedGame) { return; } analytics.trackEvent('game_resumed', { ...initialGameSettings, ...settings, isPWA, }); try { if (settings.goFullscreenOnStart) { fullscreen.enableFullscreen(); } } catch (error) { console.error(error); } if (settings.keepAwake && !wakeLock.active) { wakeLock.request(); } setInitialGameSettings(savedGame.initialGameSettings); setPlayers(savedGame.players); saveCurrentGame(null); setRandomizingPlayer(false); setShowPlay(true); setPlaying(true); tracked = false; }; const openInfo = () => { if (infoDialogRef.current) { infoDialogRef.current.showModal(); } }; const openSettings = () => { if (settingsDialogRef.current) { settingsDialogRef.current.showModal(); version.checkForNewVersion('settings'); } }; return ( <>
{ openInfo(); }} />

Life Trinket
v{version.installedVersion}

{ if (e.target.checked) { setPlayerOptions({ ...playerOptions, useCommanderDamage: e.target.checked, ...commanderSettings, }); return; } setPlayerOptions({ ...playerOptions, useCommanderDamage: e.target.checked, ...standardSettings, }); }} />
v{version.remoteVersion} available!
Number of Players { setPlayerOptions({ ...playerOptions, numberOfPlayers: Number.parseInt(e.target.value), orientation: Orientation.Landscape, }); }} />
1
2
3
4
5
6
Starting Health setPlayerOptions({ ...playerOptions, startingLifeTotal: Number.parseInt(e.target.value), orientation: Orientation.Landscape, }) } />
20
30
40
50
60
Layout { setPlayerOptions({ ...playerOptions, orientation, }); }} />
{!isPWA && (

If you're on iOS, this page works better if you{' '} hide the toolbar or{' '} add the app to your home screen.

)}
{savedGame && ( )}
); }; export default Start;