diff --git a/src/App.tsx b/src/App.tsx index 8d813dc..158df35 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,8 @@ -import { useEffect, useState } from 'react'; -import styled, { createGlobalStyle } from 'styled-components'; -import Play from './Components/Views/Play'; -import StartMenu from './Components/Views/StartMenu/StartMenu'; -import { InitialSettings } from './Data/getInitialPlayers'; - +import { createGlobalStyle } from 'styled-components'; import { ThemeProvider } from '@mui/material'; -import { useWakeLock } from 'react-screen-wake-lock'; +import { LifeTrinket } from './Components/LifeTrinket'; import { theme } from './Data/theme'; -import { useAnalytics } from './Hooks/useAnalytics'; +import { GlobalSettingsProvider } from './Providers/GlobalSettingsProvider'; import { PlayersProvider } from './Providers/PlayersProvider'; const GlobalStyles = createGlobalStyle` @@ -20,111 +15,14 @@ const GlobalStyles = createGlobalStyle` } `; -const StartWrapper = styled.div` - max-width: fit-content; - max-height: fit-content; -`; - -const PlayWrapper = styled.div` - position: relative; - z-index: 0; - max-width: fit-content; - max-height: fit-content; - @media (orientation: portrait) { - rotate: 90deg; - } -`; - -const EmergencyResetButton = styled.button` - width: 100vmax; - height: 100vmin; - font-size: 4vmax; - position: absolute; - top: 0; - z-index: -1; - background-color: #4e6815; -`; - const App = () => { - const analytics = useAnalytics(); - const savedGameSettings = localStorage.getItem('initialGameSettings'); - const savedShowPlay = localStorage.getItem('showPlay'); - - const { isSupported, release, released, request, type } = useWakeLock(); - const [initialGameSettings, setInitialGameSettings] = - useState( - savedGameSettings ? JSON.parse(savedGameSettings) : null - ); - const [showPlay, setShowPlay] = useState( - savedShowPlay ? savedShowPlay === 'true' : false - ); - - const isActive = released === undefined ? false : !released; - - const wakeLock = { - isSupported, - release, - active: isActive, - request, - type, - }; - - useEffect(() => { - localStorage.setItem( - 'initialGameSettings', - JSON.stringify(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 ( - {showPlay && initialGameSettings ? ( - - - -

If you can see this, something is wrong.

-

Press screen to go to start.

-
-

If the issue persists, please inform me.

-
-
- ) : ( - - - - )} + + +
); diff --git a/src/Components/LifeTrinket.tsx b/src/Components/LifeTrinket.tsx new file mode 100644 index 0000000..6cf3595 --- /dev/null +++ b/src/Components/LifeTrinket.tsx @@ -0,0 +1,114 @@ +import { useState, useEffect } from 'react'; +import { useWakeLock } from 'react-screen-wake-lock'; +import styled from 'styled-components'; +import { InitialSettings } from '../Data/getInitialPlayers'; +import { useAnalytics } from '../Hooks/useAnalytics'; +import Play from './Views/Play'; +import StartMenu from './Views/StartMenu/StartMenu'; + +const StartWrapper = styled.div` + max-width: fit-content; + max-height: fit-content; +`; + +const PlayWrapper = styled.div` + position: relative; + z-index: 0; + max-width: fit-content; + max-height: fit-content; + @media (orientation: portrait) { + rotate: 90deg; + } +`; + +const EmergencyResetButton = styled.button` + width: 100vmax; + height: 100vmin; + font-size: 4vmax; + position: absolute; + top: 0; + z-index: -1; + background-color: #4e6815; +`; + +export const LifeTrinket = () => { + const analytics = useAnalytics(); + const savedGameSettings = localStorage.getItem('initialGameSettings'); + const savedShowPlay = localStorage.getItem('showPlay'); + + const { isSupported, release, released, request, type } = useWakeLock(); + const [initialGameSettings, setInitialGameSettings] = + useState( + savedGameSettings ? JSON.parse(savedGameSettings) : null + ); + const [showPlay, setShowPlay] = useState( + savedShowPlay ? savedShowPlay === 'true' : false + ); + + const isActive = released === undefined ? false : !released; + + const wakeLock = { + isSupported, + release, + active: isActive, + request, + type, + }; + + useEffect(() => { + localStorage.setItem( + 'initialGameSettings', + JSON.stringify(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 ( + <> + {showPlay && initialGameSettings ? ( + + + +

If you can see this, something is wrong.

+

Press screen to go to start.

+
+

If the issue persists, please inform me.

+
+
+ ) : ( + + + + )} + + ); +}; diff --git a/src/Components/PlayerMenu/Settings.tsx b/src/Components/PlayerMenu/Settings.tsx index ea0e988..b855213 100644 --- a/src/Components/PlayerMenu/Settings.tsx +++ b/src/Components/PlayerMenu/Settings.tsx @@ -11,9 +11,9 @@ import { } from '../../Icons/generated'; import { Player, Rotation } from '../../Types/Player'; import { WakeLock } from '../../Types/WakeLock'; -import { useFullscreen } from '../../Hooks/useFullscreen'; import { theme } from '../../Data/theme'; import { InitialSettings } from '../../Data/getInitialPlayers'; +import { useGlobalSettings } from '../../Hooks/useGlobalSettings'; const SettingsContainer = styled.div<{ $rotation: Rotation; @@ -145,7 +145,8 @@ const Settings = ({ opponents, setShowPlayerMenu, }: SettingsProps) => { - const { disableFullscreen, enableFullscreen, isFullscreen } = useFullscreen(); + const { disableFullscreen, enableFullscreen, isFullscreen } = + useGlobalSettings(); const isSide = player.settings.rotation === Rotation.Side || player.settings.rotation === Rotation.SideFlipped; diff --git a/src/Components/Views/StartMenu/StartMenu.tsx b/src/Components/Views/StartMenu/StartMenu.tsx index 98806c8..935be2c 100644 --- a/src/Components/Views/StartMenu/StartMenu.tsx +++ b/src/Components/Views/StartMenu/StartMenu.tsx @@ -15,9 +15,9 @@ import { InfoModal } from '../../Misc/InfoModal'; import { SupportMe } from '../../Misc/SupportMe'; import { H2, Paragraph } from '../../Misc/TextComponents'; import LayoutOptions from './LayoutOptions'; -import { useFullscreen } from '../../../Hooks/useFullscreen'; import { Spacer } from '../../Misc/Spacer'; import { usePlayers } from '../../../Hooks/usePlayers'; +import { useGlobalSettings } from '../../../Hooks/useGlobalSettings'; const MainWrapper = styled.div` width: 100dvw; @@ -124,7 +124,7 @@ const Start = ({ ); const [wakeLockActive, setWakeLockActive] = useState(true); - const { enableFullscreen } = useFullscreen(); + const { enableFullscreen } = useGlobalSettings(); const toggleWakeLock = () => { if (wakeLock.active && wakeLockActive) { diff --git a/src/Contexts/GlobalSettingsContext.tsx b/src/Contexts/GlobalSettingsContext.tsx new file mode 100644 index 0000000..56b1d42 --- /dev/null +++ b/src/Contexts/GlobalSettingsContext.tsx @@ -0,0 +1,10 @@ +import { createContext } from 'react'; + +export type GlobalSettingsContextType = { + isFullscreen: boolean; + enableFullscreen: () => void; + disableFullscreen: () => void; +}; + +export const GlobalSettingsContext = + createContext(null); diff --git a/src/Hooks/useGlobalSettings.ts b/src/Hooks/useGlobalSettings.ts new file mode 100644 index 0000000..2c65cf7 --- /dev/null +++ b/src/Hooks/useGlobalSettings.ts @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { GlobalSettingsContext } from '../Contexts/GlobalSettingsContext'; + +export const useGlobalSettings = () => { + const context = useContext(GlobalSettingsContext); + + if (!context) { + throw new Error('useGlobalSettings hook had an issue with the context'); + } + + return { ...context }; +}; diff --git a/src/Hooks/useFullscreen.ts b/src/Providers/GlobalSettingsProvider.tsx similarity index 58% rename from src/Hooks/useFullscreen.ts rename to src/Providers/GlobalSettingsProvider.tsx index d2ba38b..5a04ad9 100644 --- a/src/Hooks/useFullscreen.ts +++ b/src/Providers/GlobalSettingsProvider.tsx @@ -1,12 +1,14 @@ -import { useEffect, useState } from 'react'; +import { ReactNode, useEffect, useMemo, useState } from 'react'; +import { + GlobalSettingsContext, + GlobalSettingsContextType, +} from '../Contexts/GlobalSettingsContext'; -type FullscreenHookReturnType = { - isFullscreen: boolean; - enableFullscreen: () => void; - disableFullscreen: () => void; -}; - -export const useFullscreen = (): FullscreenHookReturnType => { +export const GlobalSettingsProvider = ({ + children, +}: { + children: ReactNode; +}) => { const [isFullscreen, setIsFullscreen] = useState(false); const enableFullscreen = () => { @@ -37,5 +39,13 @@ export const useFullscreen = (): FullscreenHookReturnType => { }; }, []); - return { isFullscreen, enableFullscreen, disableFullscreen }; + const ctxValue = useMemo((): GlobalSettingsContextType => { + return { isFullscreen, enableFullscreen, disableFullscreen }; + }, [isFullscreen]); + + return ( + + {children} + + ); };