better life handling

This commit is contained in:
Viktor Rådberg
2023-09-22 13:13:29 +02:00
parent d7d9d26540
commit 4157ef53c1
15 changed files with 197 additions and 268 deletions

View File

@@ -4,6 +4,7 @@ import { Player, Rotation } from '../../Types/Player';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { OutlinedText } from '../Misc/OutlinedText'; import { OutlinedText } from '../Misc/OutlinedText';
import { decrementTimeoutMs } from '../../Data/constants'; import { decrementTimeoutMs } from '../../Data/constants';
import { usePlayers } from '../../Hooks/usePlayers';
const CommanderDamageContainer = styled.div<{ const CommanderDamageContainer = styled.div<{
$rotation: number; $rotation: number;
@@ -108,8 +109,7 @@ const PartnerDamageSeperator = styled.div<{
type CommanderDamageButtonComponentProps = { type CommanderDamageButtonComponentProps = {
player: Player; player: Player;
opponent: Player; opponent: Player;
onPlayerChange: (updatedPlayer: Player) => void; handleLifeChange: (updatedLifeTotal: number) => void;
setLifeTotal: (lifeTotal: number) => void;
}; };
type InputProps = { type InputProps = {
@@ -120,9 +120,9 @@ type InputProps = {
export const CommanderDamage = ({ export const CommanderDamage = ({
player, player,
opponent, opponent,
onPlayerChange, handleLifeChange,
setLifeTotal,
}: CommanderDamageButtonComponentProps) => { }: CommanderDamageButtonComponentProps) => {
const { updatePlayer } = usePlayers();
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined); const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const [timeoutFinished, setTimeoutFinished] = useState(false); const [timeoutFinished, setTimeoutFinished] = useState(false);
const [hasPressedDown, setHasPressedDown] = useState(false); const [hasPressedDown, setHasPressedDown] = useState(false);
@@ -149,8 +149,8 @@ export const CommanderDamage = ({
...player, ...player,
commanderDamage: updatedCommanderDamage, commanderDamage: updatedCommanderDamage,
}; };
onPlayerChange(updatedPlayer); updatePlayer(updatedPlayer);
setLifeTotal(player.lifeTotal - increment); handleLifeChange(player.lifeTotal - increment);
return; return;
} }
if (currentCommanderDamage.damageTotal === 0 && increment === -1) { if (currentCommanderDamage.damageTotal === 0 && increment === -1) {
@@ -164,8 +164,8 @@ export const CommanderDamage = ({
...player, ...player,
commanderDamage: updatedCommanderDamage, commanderDamage: updatedCommanderDamage,
}; };
onPlayerChange(updatedPlayer); updatePlayer(updatedPlayer);
setLifeTotal(player.lifeTotal - increment); handleLifeChange(player.lifeTotal - increment);
}; };
const handleDownInput = ({ opponentIndex, isPartner }: InputProps) => { const handleDownInput = ({ opponentIndex, isPartner }: InputProps) => {

View File

@@ -26,15 +26,13 @@ const CommanderDamageGrid = styled.div<{ $rotation: number }>`
type CommanderDamageBarProps = { type CommanderDamageBarProps = {
opponents: Player[]; opponents: Player[];
player: Player; player: Player;
onPlayerChange: (updatedPlayer: Player) => void; handleLifeChange: (updatedLifeTotal: number) => void;
setLifeTotal: (lifeTotal: number) => void;
}; };
const CommanderDamageBar = ({ const CommanderDamageBar = ({
opponents, opponents,
player, player,
onPlayerChange, handleLifeChange,
setLifeTotal,
}: CommanderDamageBarProps) => { }: CommanderDamageBarProps) => {
return ( return (
<CommanderDamageGrid <CommanderDamageGrid
@@ -49,9 +47,8 @@ const CommanderDamageBar = ({
<CommanderDamage <CommanderDamage
player={player} player={player}
opponent={opponent} opponent={opponent}
setLifeTotal={setLifeTotal}
onPlayerChange={onPlayerChange}
key={opponent.index} key={opponent.index}
handleLifeChange={handleLifeChange}
/> />
); );
})} })}

View File

@@ -1,7 +1,6 @@
import { Player } from '../../Types/Player';
import { WakeLock } from '../../Types/WakeLock';
import LifeCounter from '../LifeCounter/LifeCounter';
import styled from 'styled-components'; import styled from 'styled-components';
import { usePlayers } from '../../Hooks/usePlayers';
import LifeCounter from '../LifeCounter/LifeCounter';
export const CountersWrapper = styled.div` export const CountersWrapper = styled.div`
width: 100%; width: 100%;
@@ -29,20 +28,11 @@ export const GridItemContainer = styled.div<{
`; `;
type CountersProps = { type CountersProps = {
players: Player[];
onPlayerChange: (updatedPlayer: Player) => void;
gridAreas: string; gridAreas: string;
goToStart: () => void;
wakeLock: WakeLock;
}; };
const Counters = ({ const Counters = ({ gridAreas }: CountersProps) => {
players, const { players } = usePlayers();
onPlayerChange,
gridAreas,
goToStart,
wakeLock,
}: CountersProps) => {
return ( return (
<CountersWrapper> <CountersWrapper>
<CountersGrid $gridTemplateAreas={gridAreas}> <CountersGrid $gridTemplateAreas={gridAreas}>
@@ -53,14 +43,10 @@ const Counters = ({
$gridArea={`player${player.index}`} $gridArea={`player${player.index}`}
> >
<LifeCounter <LifeCounter
backgroundColor={player.color}
player={player} player={player}
opponents={players.filter( opponents={players.filter(
(opponent) => opponent.index !== player.index (opponent) => opponent.index !== player.index
)} )}
onPlayerChange={onPlayerChange}
goToStart={goToStart}
wakeLock={wakeLock}
/> />
</GridItemContainer> </GridItemContainer>
); );

View File

@@ -10,6 +10,7 @@ import {
PartnerTax, PartnerTax,
Poison, Poison,
} from '../../Icons/generated'; } from '../../Icons/generated';
import { usePlayers } from '../../Hooks/usePlayers';
const Container = styled.div<{ $rotation: Rotation }>` const Container = styled.div<{ $rotation: Rotation }>`
width: 100%; width: 100%;
@@ -56,13 +57,11 @@ const ExtraCountersGrid = styled.div<{ $rotation: Rotation }>`
type ExtraCountersBarProps = { type ExtraCountersBarProps = {
player: Player; player: Player;
onPlayerChange: (updatedPlayer: Player) => void;
}; };
const ExtraCountersBar = ({ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
player, const { updatePlayer } = usePlayers();
onPlayerChange,
}: ExtraCountersBarProps) => {
const handleCounterChange = ( const handleCounterChange = (
updatedCounterTotal: number, updatedCounterTotal: number,
type: CounterType type: CounterType
@@ -82,7 +81,7 @@ const ExtraCountersBar = ({
}; };
const updatedExtraCounters = [...player.extraCounters, newCounter]; const updatedExtraCounters = [...player.extraCounters, newCounter];
const updatedPlayer = { ...player, extraCounters: updatedExtraCounters }; const updatedPlayer = { ...player, extraCounters: updatedExtraCounters };
onPlayerChange(updatedPlayer); updatePlayer(updatedPlayer);
return; return;
} }
@@ -94,7 +93,7 @@ const ExtraCountersBar = ({
}); });
const updatedPlayer = { ...player, extraCounters: updatedExtraCounters }; const updatedPlayer = { ...player, extraCounters: updatedExtraCounters };
onPlayerChange(updatedPlayer); updatePlayer(updatedPlayer);
}; };
const iconSize = const iconSize =

View File

@@ -96,46 +96,25 @@ export const RecentDifference = styled.span`
type HealthProps = { type HealthProps = {
player: Player; player: Player;
onPlayerChange: (updatedPlayer: Player) => void;
differenceKey: number;
setDifferenceKey: (key: number) => void;
rotation: Rotation; rotation: Rotation;
handleLifeChange: (updatedLifeTotal: number) => void;
differenceKey: number;
recentDifference: number;
}; };
const Health = ({ const Health = ({
player, player,
onPlayerChange,
differenceKey,
setDifferenceKey,
rotation, rotation,
handleLifeChange,
differenceKey,
recentDifference,
}: HealthProps) => { }: HealthProps) => {
const handleLifeChange = (updatedLifeTotal: number) => {
const difference = updatedLifeTotal - player.lifeTotal;
const updatedPlayer = {
...player,
lifeTotal: updatedLifeTotal,
hasLost: false,
};
setRecentDifference(recentDifference + difference);
onPlayerChange(updatedPlayer);
setDifferenceKey(Date.now());
};
const [recentDifference, setRecentDifference] = useState(0);
const [showStartingPlayer, setShowStartingPlayer] = useState( const [showStartingPlayer, setShowStartingPlayer] = useState(
localStorage.getItem('playing') === 'true' localStorage.getItem('playing') === 'true'
); );
const [fontSize, setFontSize] = useState(16); const [fontSize, setFontSize] = useState(16);
const textContainerRef = useRef<HTMLDivElement | null>(null); const textContainerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const timer = setTimeout(() => {
setRecentDifference(0);
}, 3_000);
return () => clearTimeout(timer);
}, [recentDifference]);
useEffect(() => { useEffect(() => {
if (!showStartingPlayer) { if (!showStartingPlayer) {
const playingTimer = setTimeout(() => { const playingTimer = setTimeout(() => {

View File

@@ -8,7 +8,7 @@ import CommanderDamageBar from '../Counters/CommanderDamageBar';
import ExtraCountersBar from '../Counters/ExtraCountersBar'; import ExtraCountersBar from '../Counters/ExtraCountersBar';
import PlayerMenu from '../PlayerMenu/PlayerMenu'; import PlayerMenu from '../PlayerMenu/PlayerMenu';
import Health from './Health'; import Health from './Health';
import { WakeLock } from '../../Types/WakeLock'; import { usePlayers } from '../../Hooks/usePlayers';
const LifeCounterContentWrapper = styled.div<{ const LifeCounterContentWrapper = styled.div<{
$backgroundColor: string; $backgroundColor: string;
@@ -160,42 +160,15 @@ const playerCanLose = (player: Player) => {
}; };
type LifeCounterProps = { type LifeCounterProps = {
backgroundColor: string;
player: Player; player: Player;
opponents: Player[]; opponents: Player[];
onPlayerChange: (updatedPlayer: Player) => void;
goToStart: () => void;
wakeLock: WakeLock;
}; };
const LifeCounter = ({ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
backgroundColor, const { updatePlayer, updateLifeTotal } = usePlayers();
player,
opponents,
onPlayerChange,
goToStart,
wakeLock,
}: LifeCounterProps) => {
const handleLifeChange = (updatedLifeTotal: number) => {
const difference = updatedLifeTotal - player.lifeTotal;
const updatedPlayer = {
...player,
lifeTotal: updatedLifeTotal,
hasLost: false,
};
setRecentDifference(recentDifference + difference);
onPlayerChange(updatedPlayer);
setDifferenceKey(Date.now());
};
const toggleGameLost = () => {
const updatedPlayer = { ...player, hasLost: !player.hasLost };
onPlayerChange(updatedPlayer);
};
const [showPlayerMenu, setShowPlayerMenu] = useState(false); const [showPlayerMenu, setShowPlayerMenu] = useState(false);
const [recentDifference, setRecentDifference] = useState(0); const [recentDifference, setRecentDifference] = useState(0);
const [differenceKey, setDifferenceKey] = useState(Date.now()); const [differenceKey, setDifferenceKey] = useState(Date.now());
useEffect(() => { useEffect(() => {
@@ -211,7 +184,7 @@ const LifeCounter = ({
const playingTimer = setTimeout(() => { const playingTimer = setTimeout(() => {
localStorage.setItem('playing', 'true'); localStorage.setItem('playing', 'true');
player.showStartingPlayer = false; player.showStartingPlayer = false;
onPlayerChange(player); updatePlayer(player);
}, 3_000); }, 3_000);
return () => clearTimeout(playingTimer); return () => clearTimeout(playingTimer);
@@ -222,8 +195,19 @@ const LifeCounter = ({
player.settings.rotation === Rotation.SideFlipped || player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side; player.settings.rotation === Rotation.Side;
const handleLifeChange = (updatedLifeTotal: number) => {
const difference = updateLifeTotal(player, updatedLifeTotal);
setRecentDifference(recentDifference + difference);
setDifferenceKey(Date.now());
};
const toggleGameLost = () => {
const updatedPlayer = { ...player, hasLost: !player.hasLost };
updatePlayer(updatedPlayer);
};
return ( return (
<LifeCounterContentWrapper $backgroundColor={backgroundColor}> <LifeCounterContentWrapper $backgroundColor={player.color}>
<LifeCounterWrapper $rotation={player.settings.rotation}> <LifeCounterWrapper $rotation={player.settings.rotation}>
{player.isStartingPlayer && player.showStartingPlayer && ( {player.isStartingPlayer && player.showStartingPlayer && (
<PlayerNoticeWrapper <PlayerNoticeWrapper
@@ -245,9 +229,8 @@ const LifeCounter = ({
<CommanderDamageBar <CommanderDamageBar
opponents={opponents} opponents={opponents}
player={player} player={player}
onPlayerChange={onPlayerChange}
setLifeTotal={handleLifeChange}
key={player.index} key={player.index}
handleLifeChange={handleLifeChange}
/> />
<SettingsButton <SettingsButton
onClick={() => { onClick={() => {
@@ -263,22 +246,19 @@ const LifeCounter = ({
)} )}
<Health <Health
player={player} player={player}
onPlayerChange={onPlayerChange}
differenceKey={differenceKey}
setDifferenceKey={setDifferenceKey}
rotation={player.settings.rotation} rotation={player.settings.rotation}
differenceKey={differenceKey}
recentDifference={recentDifference}
handleLifeChange={handleLifeChange}
/> />
<ExtraCountersBar player={player} onPlayerChange={onPlayerChange} /> <ExtraCountersBar player={player} />
</LifeCounterWrapper> </LifeCounterWrapper>
{showPlayerMenu && ( {showPlayerMenu && (
<PlayerMenu <PlayerMenu
player={player} player={player}
opponents={opponents} opponents={opponents}
onPlayerChange={onPlayerChange}
setShowPlayerMenu={setShowPlayerMenu} setShowPlayerMenu={setShowPlayerMenu}
goToStart={goToStart}
wakeLock={wakeLock}
/> />
)} )}
</LifeCounterContentWrapper> </LifeCounterContentWrapper>

View File

@@ -1,10 +1,9 @@
import { useState, useEffect } from 'react'; import { useEffect, useState } from 'react';
import { useWakeLock } from 'react-screen-wake-lock';
import styled from 'styled-components'; import styled from 'styled-components';
import { InitialSettings } from '../Data/getInitialPlayers'; import { InitialSettings } from '../Data/getInitialPlayers';
import { useAnalytics } from '../Hooks/useAnalytics';
import Play from './Views/Play'; import Play from './Views/Play';
import StartMenu from './Views/StartMenu/StartMenu'; import StartMenu from './Views/StartMenu/StartMenu';
import { useGlobalSettings } from '../Hooks/useGlobalSettings';
const StartWrapper = styled.div` const StartWrapper = styled.div`
max-width: fit-content; max-width: fit-content;
@@ -32,28 +31,14 @@ const EmergencyResetButton = styled.button`
`; `;
export const LifeTrinket = () => { export const LifeTrinket = () => {
const analytics = useAnalytics();
const savedGameSettings = localStorage.getItem('initialGameSettings'); const savedGameSettings = localStorage.getItem('initialGameSettings');
const savedShowPlay = localStorage.getItem('showPlay');
const { isSupported, release, released, request, type } = useWakeLock(); const { showPlay, goToStart } = useGlobalSettings();
const [initialGameSettings, setInitialGameSettings] = const [initialGameSettings, setInitialGameSettings] =
useState<InitialSettings | null>( useState<InitialSettings | null>(
savedGameSettings ? JSON.parse(savedGameSettings) : null savedGameSettings ? JSON.parse(savedGameSettings) : null
); );
const [showPlay, setShowPlay] = useState<boolean>(
savedShowPlay ? savedShowPlay === 'true' : false
);
const isActive = released === undefined ? false : !released;
const wakeLock = {
isSupported,
release,
active: isActive,
request,
type,
};
useEffect(() => { useEffect(() => {
localStorage.setItem( localStorage.setItem(
@@ -62,36 +47,11 @@ export const LifeTrinket = () => {
); );
}, [initialGameSettings]); }, [initialGameSettings]);
const removeLocalStorage = async () => {
localStorage.removeItem('initialGameSettings');
localStorage.removeItem('players');
localStorage.removeItem('playing');
localStorage.removeItem('showPlay');
setShowPlay(localStorage.getItem('showPlay') === 'true' ?? false);
};
const goToStart = async () => {
// this function is broken for the moment, need to set players object
const currentPlayers = localStorage.getItem('players');
if (currentPlayers) {
analytics.trackEvent('go_to_start', {
playersBeforeReset: currentPlayers,
});
}
await removeLocalStorage();
// setPlayers([]);
};
return ( return (
<> <>
{showPlay && initialGameSettings ? ( {showPlay && initialGameSettings ? (
<PlayWrapper> <PlayWrapper>
<Play <Play gridAreas={initialGameSettings?.gridAreas} />
gridAreas={initialGameSettings?.gridAreas}
goToStart={goToStart}
wakeLock={wakeLock}
/>
<EmergencyResetButton onClick={goToStart}> <EmergencyResetButton onClick={goToStart}>
<p>If you can see this, something is wrong.</p> <p>If you can see this, something is wrong.</p>
<p>Press screen to go to start.</p> <p>Press screen to go to start.</p>
@@ -104,8 +64,6 @@ export const LifeTrinket = () => {
<StartMenu <StartMenu
initialGameSettings={initialGameSettings} initialGameSettings={initialGameSettings}
setInitialGameSettings={setInitialGameSettings} setInitialGameSettings={setInitialGameSettings}
wakeLock={wakeLock}
setShowPlay={setShowPlay}
/> />
</StartWrapper> </StartWrapper>
)} )}

View File

@@ -1,10 +1,7 @@
import { Player } from '../../Types/Player';
import Settings from './Settings';
import styled from 'styled-components';
import { css } from 'styled-components';
import { Rotation } from '../../Types/Player';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import { WakeLock } from '../../Types/WakeLock'; import styled, { css } from 'styled-components';
import { Player, Rotation } from '../../Types/Player';
import Settings from './Settings';
const PlayerMenuWrapper = styled.div<{ const PlayerMenuWrapper = styled.div<{
$rotation: Rotation; $rotation: Rotation;
@@ -66,19 +63,13 @@ const CloseButton = styled.div<{
type PlayerMenuProps = { type PlayerMenuProps = {
player: Player; player: Player;
opponents: Player[]; opponents: Player[];
onPlayerChange: (updatedPlayer: Player) => void;
setShowPlayerMenu: (showPlayerMenu: boolean) => void; setShowPlayerMenu: (showPlayerMenu: boolean) => void;
goToStart: () => void;
wakeLock: WakeLock;
}; };
const PlayerMenu = ({ const PlayerMenu = ({
player, player,
opponents, opponents,
onPlayerChange,
setShowPlayerMenu, setShowPlayerMenu,
goToStart,
wakeLock,
}: PlayerMenuProps) => { }: PlayerMenuProps) => {
const handleOnClick = () => { const handleOnClick = () => {
setShowPlayerMenu(false); setShowPlayerMenu(false);
@@ -100,10 +91,7 @@ const PlayerMenu = ({
</CloseButton> </CloseButton>
<Settings <Settings
player={player} player={player}
onChange={onPlayerChange}
opponents={opponents} opponents={opponents}
goToStart={goToStart}
wakeLock={wakeLock}
setShowPlayerMenu={setShowPlayerMenu} setShowPlayerMenu={setShowPlayerMenu}
/> />
</PlayerMenuWrapper> </PlayerMenuWrapper>

View File

@@ -1,5 +1,8 @@
import { Button, Checkbox } from '@mui/material'; import { Button, Checkbox } from '@mui/material';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import { InitialSettings } from '../../Data/getInitialPlayers';
import { theme } from '../../Data/theme';
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
import { import {
Energy, Energy,
Exit, Exit,
@@ -10,10 +13,7 @@ import {
Poison, Poison,
} from '../../Icons/generated'; } from '../../Icons/generated';
import { Player, Rotation } from '../../Types/Player'; import { Player, Rotation } from '../../Types/Player';
import { WakeLock } from '../../Types/WakeLock'; import { usePlayers } from '../../Hooks/usePlayers';
import { theme } from '../../Data/theme';
import { InitialSettings } from '../../Data/getInitialPlayers';
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
const SettingsContainer = styled.div<{ const SettingsContainer = styled.div<{
$rotation: Rotation; $rotation: Rotation;
@@ -131,45 +131,26 @@ const CheckboxContainer = styled.div<{ $rotation: Rotation }>`
type SettingsProps = { type SettingsProps = {
player: Player; player: Player;
opponents: Player[]; opponents: Player[];
onChange: (updatedPlayer: Player) => void;
goToStart: () => void;
wakeLock: WakeLock;
setShowPlayerMenu: (showPlayerMenu: boolean) => void; setShowPlayerMenu: (showPlayerMenu: boolean) => void;
}; };
const Settings = ({ const Settings = ({ player, opponents, setShowPlayerMenu }: SettingsProps) => {
player, const { fullscreen, wakeLock, goToStart } = useGlobalSettings();
onChange, const { updatePlayer } = usePlayers();
goToStart,
wakeLock,
opponents,
setShowPlayerMenu,
}: SettingsProps) => {
const { disableFullscreen, enableFullscreen, isFullscreen } =
useGlobalSettings();
const isSide = const isSide =
player.settings.rotation === Rotation.Side || player.settings.rotation === Rotation.Side ||
player.settings.rotation === Rotation.SideFlipped; player.settings.rotation === Rotation.SideFlipped;
const handleWakeLock = () => {
if (!wakeLock.active) {
wakeLock.request();
return;
}
wakeLock.release();
};
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => { const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const updatedPlayer = { ...player, color: event.target.value }; const updatedPlayer = { ...player, color: event.target.value };
onChange(updatedPlayer); updatePlayer(updatedPlayer);
}; };
const handleSettingsChange = (event: React.ChangeEvent<HTMLInputElement>) => { const handleSettingsChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, checked } = event.target; const { name, checked } = event.target;
const updatedSettings = { ...player.settings, [name]: checked }; const updatedSettings = { ...player.settings, [name]: checked };
const updatedPlayer = { ...player, settings: updatedSettings }; const updatedPlayer = { ...player, settings: updatedSettings };
onChange(updatedPlayer); updatePlayer(updatedPlayer);
}; };
const handleResetGame = () => { const handleResetGame = () => {
@@ -209,21 +190,17 @@ const Settings = ({
player.showStartingPlayer = true; player.showStartingPlayer = true;
} }
onChange(player); updatePlayer(player);
}); });
localStorage.setItem('playing', 'false'); localStorage.setItem('playing', 'false');
setShowPlayerMenu(false); setShowPlayerMenu(false);
}; };
const handleNewGame = () => {
goToStart();
};
const toggleFullscreen = () => { const toggleFullscreen = () => {
if (isFullscreen) { if (fullscreen.isFullscreen) {
disableFullscreen(); fullscreen.disableFullscreen();
} else { } else {
enableFullscreen(); fullscreen.enableFullscreen();
} }
}; };
@@ -357,7 +334,7 @@ const Settings = ({
cursor: 'pointer', cursor: 'pointer',
userSelect: 'none', userSelect: 'none',
}} }}
onClick={handleNewGame} onClick={goToStart}
aria-label="Back to start" aria-label="Back to start"
> >
<Exit size="4vmax" style={{ rotate: '180deg' }} /> <Exit size="4vmax" style={{ rotate: '180deg' }} />
@@ -385,7 +362,7 @@ const Settings = ({
fontSize: buttonFontSize, fontSize: buttonFontSize,
padding: '0 4px 0 4px', padding: '0 4px 0 4px',
}} }}
onClick={handleWakeLock} onClick={wakeLock.toggleWakeLock}
role="checkbox" role="checkbox"
aria-checked={wakeLock.active} aria-checked={wakeLock.active}
aria-label="Keep awake" aria-label="Keep awake"

View File

@@ -1,6 +1,4 @@
import styled from 'styled-components'; import styled from 'styled-components';
import { usePlayers } from '../../Hooks/usePlayers';
import { WakeLock } from '../../Types/WakeLock';
import Counters from '../Counters/Counters'; import Counters from '../Counters/Counters';
const MainWrapper = styled.div` const MainWrapper = styled.div`
@@ -13,21 +11,12 @@ const MainWrapper = styled.div`
type PlayProps = { type PlayProps = {
gridAreas: string; gridAreas: string;
goToStart: () => void;
wakeLock: WakeLock;
}; };
const Play = ({ gridAreas, goToStart, wakeLock }: PlayProps) => { const Play = ({ gridAreas }: PlayProps) => {
const { players, updatePlayer } = usePlayers();
return ( return (
<MainWrapper> <MainWrapper>
<Counters <Counters gridAreas={gridAreas} />
players={players}
onPlayerChange={updatePlayer}
gridAreas={gridAreas}
goToStart={goToStart}
wakeLock={wakeLock}
/>
</MainWrapper> </MainWrapper>
); );
}; };

View File

@@ -10,7 +10,6 @@ import {
import { theme } from '../../../Data/theme'; import { theme } from '../../../Data/theme';
import { useAnalytics } from '../../../Hooks/useAnalytics'; import { useAnalytics } from '../../../Hooks/useAnalytics';
import { Info } from '../../../Icons/generated'; import { Info } from '../../../Icons/generated';
import { WakeLock } from '../../../Types/WakeLock';
import { InfoModal } from '../../Misc/InfoModal'; import { InfoModal } from '../../Misc/InfoModal';
import { SupportMe } from '../../Misc/SupportMe'; import { SupportMe } from '../../Misc/SupportMe';
import { H2, Paragraph } from '../../Misc/TextComponents'; import { H2, Paragraph } from '../../Misc/TextComponents';
@@ -101,19 +100,16 @@ const healthMarks = [
type StartProps = { type StartProps = {
setInitialGameSettings: (options: InitialSettings) => void; setInitialGameSettings: (options: InitialSettings) => void;
initialGameSettings: InitialSettings | null; initialGameSettings: InitialSettings | null;
wakeLock: WakeLock;
setShowPlay: (showPlay: boolean) => void;
}; };
const Start = ({ const Start = ({ initialGameSettings, setInitialGameSettings }: StartProps) => {
initialGameSettings,
setInitialGameSettings,
wakeLock,
setShowPlay,
}: StartProps) => {
const { setPlayers } = usePlayers(); const { setPlayers } = usePlayers();
const analytics = useAnalytics(); const analytics = useAnalytics();
const { fullscreen, wakeLock, setShowPlay } = useGlobalSettings();
const [openModal, setOpenModal] = useState(false); const [openModal, setOpenModal] = useState(false);
const [keepAwake, setKeepAwake] = useState(true);
const [playerOptions, setPlayerOptions] = useState<InitialSettings>( const [playerOptions, setPlayerOptions] = useState<InitialSettings>(
initialGameSettings || { initialGameSettings || {
numberOfPlayers: 4, numberOfPlayers: 4,
@@ -122,25 +118,6 @@ const Start = ({
gridAreas: GridTemplateAreas.FourPlayers, gridAreas: GridTemplateAreas.FourPlayers,
} }
); );
const [wakeLockActive, setWakeLockActive] = useState(true);
const { enableFullscreen } = useGlobalSettings();
const toggleWakeLock = () => {
if (wakeLock.active && wakeLockActive) {
wakeLock.release();
setWakeLockActive(false);
return;
}
if (!wakeLock.active && !wakeLockActive) {
wakeLock.request();
setWakeLockActive(true);
return;
}
setWakeLockActive(wakeLock.active);
};
const doStartGame = () => { const doStartGame = () => {
if (!initialGameSettings) { if (!initialGameSettings) {
@@ -149,16 +126,18 @@ const Start = ({
analytics.trackEvent('game_started', { ...initialGameSettings }); analytics.trackEvent('game_started', { ...initialGameSettings });
if (!wakeLock.active && wakeLockActive) {
wakeLock.request();
}
try { try {
enableFullscreen(); fullscreen.enableFullscreen();
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
console.log('go to start', wakeLock.active);
if (keepAwake) {
wakeLock.request();
}
setInitialGameSettings(initialGameSettings); setInitialGameSettings(initialGameSettings);
setPlayers(createInitialPlayers(initialGameSettings)); setPlayers(createInitialPlayers(initialGameSettings));
setShowPlay(true); setShowPlay(true);
@@ -294,8 +273,8 @@ const Start = ({
<ToggleContainer> <ToggleContainer>
<FormLabel>Keep Awake</FormLabel> <FormLabel>Keep Awake</FormLabel>
<Switch <Switch
checked={wakeLockActive} checked={keepAwake}
onChange={() => toggleWakeLock()} onChange={() => setKeepAwake(!keepAwake)}
/> />
</ToggleContainer> </ToggleContainer>
</ToggleButtonsWrapper> </ToggleButtonsWrapper>

View File

@@ -1,9 +1,22 @@
import { createContext } from 'react'; import { createContext } from 'react';
export type GlobalSettingsContextType = { export type GlobalSettingsContextType = {
isFullscreen: boolean; fullscreen: {
enableFullscreen: () => void; isFullscreen: boolean;
disableFullscreen: () => void; enableFullscreen: () => void;
disableFullscreen: () => void;
};
wakeLock: {
isSupported: boolean;
release: () => void;
active: boolean;
request: () => void;
type: 'screen' | undefined;
toggleWakeLock: () => void;
};
goToStart: () => void;
showPlay: boolean;
setShowPlay: (showPlay: boolean) => void;
}; };
export const GlobalSettingsContext = export const GlobalSettingsContext =

View File

@@ -5,6 +5,7 @@ export type PlayersContextType = {
players: Player[] | []; players: Player[] | [];
setPlayers: (players: Player[]) => void; setPlayers: (players: Player[]) => void;
updatePlayer: (updatedPlayer: Player) => void; updatePlayer: (updatedPlayer: Player) => void;
updateLifeTotal: (player: Player, updatedLifeTotal: number) => number;
}; };
export const PlayersContext = createContext<PlayersContextType | null>(null); export const PlayersContext = createContext<PlayersContextType | null>(null);

View File

@@ -3,12 +3,21 @@ import {
GlobalSettingsContext, GlobalSettingsContext,
GlobalSettingsContextType, GlobalSettingsContextType,
} from '../Contexts/GlobalSettingsContext'; } from '../Contexts/GlobalSettingsContext';
import { useWakeLock } from 'react-screen-wake-lock';
import { useAnalytics } from '../Hooks/useAnalytics';
export const GlobalSettingsProvider = ({ export const GlobalSettingsProvider = ({
children, children,
}: { }: {
children: ReactNode; children: ReactNode;
}) => { }) => {
const analytics = useAnalytics();
const savedShowPlay = localStorage.getItem('showPlay');
const [showPlay, setShowPlay] = useState<boolean>(
savedShowPlay ? savedShowPlay === 'true' : false
);
const [isFullscreen, setIsFullscreen] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false);
const enableFullscreen = () => { const enableFullscreen = () => {
@@ -39,9 +48,67 @@ export const GlobalSettingsProvider = ({
}; };
}, []); }, []);
const { isSupported, release, released, request, type } = useWakeLock();
const active = released === undefined ? false : !released;
const removeLocalStorage = async () => {
localStorage.removeItem('initialGameSettings');
localStorage.removeItem('players');
localStorage.removeItem('playing');
localStorage.removeItem('showPlay');
setShowPlay(localStorage.getItem('showPlay') === 'true' ?? false);
};
const ctxValue = useMemo((): GlobalSettingsContextType => { const ctxValue = useMemo((): GlobalSettingsContextType => {
return { isFullscreen, enableFullscreen, disableFullscreen }; const goToStart = async () => {
}, [isFullscreen]); // this function is broken for the moment, need to set players object
const currentPlayers = localStorage.getItem('players');
if (currentPlayers) {
analytics.trackEvent('go_to_start', {
playersBeforeReset: currentPlayers,
});
}
await removeLocalStorage();
// setPlayers([]);
};
const toggleWakeLock = async () => {
if (active) {
release();
return;
}
request();
};
return {
fullscreen: { isFullscreen, enableFullscreen, disableFullscreen },
wakeLock: {
isSupported,
release,
active,
request,
type,
toggleWakeLock,
},
goToStart,
showPlay,
setShowPlay,
};
}, [
active,
analytics,
isFullscreen,
isSupported,
release,
request,
showPlay,
type,
]);
return ( return (
<GlobalSettingsContext.Provider value={ctxValue}> <GlobalSettingsContext.Provider value={ctxValue}>

View File

@@ -14,19 +14,35 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
localStorage.setItem('players', JSON.stringify(players)); localStorage.setItem('players', JSON.stringify(players));
}, [players]); }, [players]);
const updatePlayer = (updatedPlayer: Player) => {
const updatedPlayers = players.map((player) =>
player.index === updatedPlayer.index ? updatedPlayer : player
);
setPlayers(updatedPlayers);
};
const ctxValue = useMemo((): PlayersContextType => { const ctxValue = useMemo((): PlayersContextType => {
const updatePlayer = (updatedPlayer: Player) => {
const updatedPlayers = players.map((player) =>
player.index === updatedPlayer.index ? updatedPlayer : player
);
setPlayers(updatedPlayers);
};
const updateLifeTotal = (
player: Player,
updatedLifeTotal: number
): number => {
const difference = updatedLifeTotal - player.lifeTotal;
const updatedPlayer = {
...player,
lifeTotal: updatedLifeTotal,
hasLost: false,
};
updatePlayer(updatedPlayer);
return difference;
};
return { return {
players, players,
setPlayers, setPlayers,
updatePlayer, updatePlayer,
updateLifeTotal,
}; };
}, [players]); }, [players]);