|
|
|
@ -1,3 +1,6 @@
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @file contains the navigation bars of the app.
|
|
|
|
|
|
|
|
*/
|
|
|
|
import * as React from 'react'
|
|
|
|
import * as React from 'react'
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
|
|
import { faDownload, faUpload, faEraser, faBook, faBookOpen, faGlobe, faHome,
|
|
|
|
import { faDownload, faUpload, faEraser, faBook, faBookOpen, faGlobe, faHome,
|
|
|
|
@ -11,7 +14,7 @@ import { useAppDispatch, useAppSelector } from '../hooks'
|
|
|
|
import { Button } from './button'
|
|
|
|
import { Button } from './button'
|
|
|
|
import { downloadProgress } from './popup/erase'
|
|
|
|
import { downloadProgress } from './popup/erase'
|
|
|
|
|
|
|
|
|
|
|
|
/** navigation buttons to switch between welcome-pages on mobile */
|
|
|
|
/** navigation buttons for mobile welcome page to switch between intro/tree/inventory. */
|
|
|
|
function MobileNavButtons({pageNumber, setPageNumber}:
|
|
|
|
function MobileNavButtons({pageNumber, setPageNumber}:
|
|
|
|
{ pageNumber: number,
|
|
|
|
{ pageNumber: number,
|
|
|
|
setPageNumber: any}) {
|
|
|
|
setPageNumber: any}) {
|
|
|
|
@ -49,61 +52,16 @@ function MobileNavButtons({pageNumber, setPageNumber}:
|
|
|
|
</>
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** button to toggle dropdown menu. */
|
|
|
|
function MenuButton({navOpen, setNavOpen}) {
|
|
|
|
function MenuButton({navOpen, setNavOpen}) {
|
|
|
|
return <Button to="" className="btn toggle-width" id="menu-btn" onClick={(ev) => {setNavOpen(!navOpen)}}>
|
|
|
|
return <Button to="" className="btn toggle-width" id="menu-btn" onClick={(ev) => {setNavOpen(!navOpen)}}>
|
|
|
|
{navOpen ? <FontAwesomeIcon icon={faXmark} /> : <FontAwesomeIcon icon={faBars} />}
|
|
|
|
{navOpen ? <FontAwesomeIcon icon={faXmark} /> : <FontAwesomeIcon icon={faBars} />}
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** the navigation bar on the welcome page */
|
|
|
|
/** button to go one level futher.
|
|
|
|
export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpressum, toggleEraseMenu, toggleUploadMenu, toggleInfo} : {
|
|
|
|
* for the last level, this button turns into a button going back to the welcome page.
|
|
|
|
pageNumber: number,
|
|
|
|
*/
|
|
|
|
setPageNumber: any,
|
|
|
|
|
|
|
|
gameInfo: GameInfo,
|
|
|
|
|
|
|
|
toggleImpressum: any,
|
|
|
|
|
|
|
|
toggleEraseMenu: any,
|
|
|
|
|
|
|
|
toggleUploadMenu: any,
|
|
|
|
|
|
|
|
toggleInfo: any
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
|
|
|
|
const gameProgress = useAppSelector(selectProgress(gameId))
|
|
|
|
|
|
|
|
const {mobile} = React.useContext(MobileContext)
|
|
|
|
|
|
|
|
const [navOpen, setNavOpen] = React.useState(false)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return <div className="app-bar">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<Button inverted="false" title="back to games selection" to="/">
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faArrowLeft} /> <FontAwesomeIcon icon={faGlobe} />
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<span className="app-bar-title"></span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
{!mobile && <span className="app-bar-title">{gameInfo?.title}</span>}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="nav-btns">
|
|
|
|
|
|
|
|
{mobile && <MobileNavButtons pageNumber={pageNumber} setPageNumber={setPageNumber} />}
|
|
|
|
|
|
|
|
<MenuButton navOpen={navOpen} setNavOpen={setNavOpen} />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={'menu dropdown' + (navOpen ? '' : ' hidden')}>
|
|
|
|
|
|
|
|
<Button title="Game Info & Credits" inverted="true" to="" onClick={() => {toggleInfo(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faCircleInfo} /> Game Info
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Clear Progress" inverted="true" to="" onClick={() => {toggleEraseMenu(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faEraser} /> Erase
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Download Progress" inverted="true" to="" onClick={(ev) => {downloadProgress(gameId, gameProgress, ev); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faDownload} /> Download
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Load Progress from JSON" inverted="true" to="" onClick={() => {toggleUploadMenu(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faUpload} /> Upload
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Impressum, privacy policy" inverted="true" to="" onClick={() => {toggleImpressum(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faCircleInfo} /> Impressum
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function NextButton({worldSize, difficulty, completed, setNavOpen}) {
|
|
|
|
function NextButton({worldSize, difficulty, completed, setNavOpen}) {
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const {worldId, levelId} = React.useContext(WorldLevelIdContext)
|
|
|
|
const {worldId, levelId} = React.useContext(WorldLevelIdContext)
|
|
|
|
@ -121,6 +79,9 @@ function NextButton({worldSize, difficulty, completed, setNavOpen}) {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** button to go one level back.
|
|
|
|
|
|
|
|
* only renders if the current level id is > 0.
|
|
|
|
|
|
|
|
*/
|
|
|
|
function PreviousButton({setNavOpen}) {
|
|
|
|
function PreviousButton({setNavOpen}) {
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const {worldId, levelId} = React.useContext(WorldLevelIdContext)
|
|
|
|
const {worldId, levelId} = React.useContext(WorldLevelIdContext)
|
|
|
|
@ -134,6 +95,7 @@ function PreviousButton({setNavOpen}) {
|
|
|
|
</>)
|
|
|
|
</>)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** button to toggle between editor and typewriter */
|
|
|
|
function InputModeButton({setNavOpen, isDropdown}) {
|
|
|
|
function InputModeButton({setNavOpen, isDropdown}) {
|
|
|
|
const {levelId} = React.useContext(WorldLevelIdContext)
|
|
|
|
const {levelId} = React.useContext(WorldLevelIdContext)
|
|
|
|
const {typewriterMode, setTypewriterMode, lockInputMode} = React.useContext(InputModeContext)
|
|
|
|
const {typewriterMode, setTypewriterMode, lockInputMode} = React.useContext(InputModeContext)
|
|
|
|
@ -156,6 +118,7 @@ function InputModeButton({setNavOpen, isDropdown}) {
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** button to toggle iimpressum popup */
|
|
|
|
function ImpressumButton({setNavOpen, toggleImpressum, isDropdown}) {
|
|
|
|
function ImpressumButton({setNavOpen, toggleImpressum, isDropdown}) {
|
|
|
|
return <Button className="btn btn-inverted toggle-width"
|
|
|
|
return <Button className="btn btn-inverted toggle-width"
|
|
|
|
title="information, Impressum, privacy policy" inverted="true" to="" onClick={(ev) => {toggleImpressum(ev); setNavOpen(false)}}>
|
|
|
|
title="information, Impressum, privacy policy" inverted="true" to="" onClick={(ev) => {toggleImpressum(ev); setNavOpen(false)}}>
|
|
|
|
@ -164,6 +127,7 @@ function ImpressumButton({setNavOpen, toggleImpressum, isDropdown}) {
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** button to go back to welcome page */
|
|
|
|
function HomeButton({isDropdown}) {
|
|
|
|
function HomeButton({isDropdown}) {
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
return <Button to={`/${gameId}`} inverted="true" title="back to world selection" id="home-btn">
|
|
|
|
return <Button to={`/${gameId}`} inverted="true" title="back to world selection" id="home-btn">
|
|
|
|
@ -172,7 +136,9 @@ function HomeButton({isDropdown}) {
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** only displays a button if `setPageNumber` is set. */
|
|
|
|
/** button in mobile level to toggle inventory.
|
|
|
|
|
|
|
|
* only displays a button if `setPageNumber` is set.
|
|
|
|
|
|
|
|
*/
|
|
|
|
function InventoryButton({pageNumber, setPageNumber}) {
|
|
|
|
function InventoryButton({pageNumber, setPageNumber}) {
|
|
|
|
return (setPageNumber &&
|
|
|
|
return (setPageNumber &&
|
|
|
|
<Button to="" className="btn btn-inverted toggle-width"
|
|
|
|
<Button to="" className="btn btn-inverted toggle-width"
|
|
|
|
@ -183,6 +149,55 @@ function InventoryButton({pageNumber, setPageNumber}) {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** the navigation bar on the welcome page */
|
|
|
|
|
|
|
|
export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpressum, toggleEraseMenu, toggleUploadMenu, toggleInfo} : {
|
|
|
|
|
|
|
|
pageNumber: number,
|
|
|
|
|
|
|
|
setPageNumber: any,
|
|
|
|
|
|
|
|
gameInfo: GameInfo,
|
|
|
|
|
|
|
|
toggleImpressum: any,
|
|
|
|
|
|
|
|
toggleEraseMenu: any,
|
|
|
|
|
|
|
|
toggleUploadMenu: any,
|
|
|
|
|
|
|
|
toggleInfo: any
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
|
|
|
|
const gameProgress = useAppSelector(selectProgress(gameId))
|
|
|
|
|
|
|
|
const {mobile} = React.useContext(MobileContext)
|
|
|
|
|
|
|
|
const [navOpen, setNavOpen] = React.useState(false)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return <div className="app-bar">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<Button inverted="false" title="back to games selection" to="/">
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faArrowLeft} /> <FontAwesomeIcon icon={faGlobe} />
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<span className="app-bar-title"></span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
{!mobile && <span className="app-bar-title">{gameInfo?.title}</span>}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="nav-btns">
|
|
|
|
|
|
|
|
{mobile && <MobileNavButtons pageNumber={pageNumber} setPageNumber={setPageNumber} />}
|
|
|
|
|
|
|
|
<MenuButton navOpen={navOpen} setNavOpen={setNavOpen} />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={'menu dropdown' + (navOpen ? '' : ' hidden')}>
|
|
|
|
|
|
|
|
<Button title="Game Info & Credits" inverted="true" to="" onClick={() => {toggleInfo(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faCircleInfo} /> Game Info
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Clear Progress" inverted="true" to="" onClick={() => {toggleEraseMenu(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faEraser} /> Erase
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Download Progress" inverted="true" to="" onClick={(ev) => {downloadProgress(gameId, gameProgress, ev); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faDownload} /> Download
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Load Progress from JSON" inverted="true" to="" onClick={() => {toggleUploadMenu(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faUpload} /> Upload
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button title="Impressum, privacy policy" inverted="true" to="" onClick={() => {toggleImpressum(); setNavOpen(false)}}>
|
|
|
|
|
|
|
|
<FontAwesomeIcon icon={faCircleInfo} /> Impressum
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** the navigation bar in a level */
|
|
|
|
/** the navigation bar in a level */
|
|
|
|
export function LevelAppBar({isLoading, levelTitle, toggleImpressum, pageNumber=undefined, setPageNumber=undefined} : {
|
|
|
|
export function LevelAppBar({isLoading, levelTitle, toggleImpressum, pageNumber=undefined, setPageNumber=undefined} : {
|
|
|
|
isLoading: boolean,
|
|
|
|
isLoading: boolean,
|
|
|
|
|