import * as React from 'react' import { useState, useEffect } from 'react' import { useSelector } from 'react-redux' import Split from 'react-split' import { Box, Typography, CircularProgress } from '@mui/material' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faGlobe, faBook, faArrowRight, faArrowLeft } from '@fortawesome/free-solid-svg-icons' import { GameIdContext } from '../app' import { useAppDispatch } from '../hooks' import { GameProgressState, changedOpenedIntro, deleteProgress, loadProgress, selectOpenedIntro, selectProgress } from '../state/progress' import { useGetGameInfoQuery, useLoadInventoryOverviewQuery } from '../state/api' import { Button } from './button' import { MobileContext } from './infoview/context' import { InventoryPanel } from './inventory' import Markdown from './markdown' import {PrivacyPolicyPopup} from './privacy_policy' import { WorldTreePanel, downloadFile } from './world_tree' import './welcome.css' import { WelcomeAppBar } from './app_bar' import { Hint } from './hints' /** The panel showing the game's introduction text */ function IntroductionPanel({introduction}: {introduction: string}) { const {mobile, setPageNumber} = React.useContext(MobileContext) const gameId = React.useContext(GameIdContext) const dispatch = useAppDispatch() // TODO: I left the setup for splitting up the introduction in place, but if it's not needed // then this can be simplified. // let text: Array = introduction.split(/\n(\s*\n)+/) let text: Array = introduction ? [introduction] : [] return
{text?.map(((t, i) => t.trim() ? : <> ))}
{/*

{title}

{introduction}
*/} {mobile &&
}
} export function InfoPopup ({info, handleClose}: {info: string, handleClose: () => void}) { return
{info}
} function ErasePopup ({handleClose}) { const gameId = React.useContext(GameIdContext) const gameProgress = useSelector(selectProgress(gameId)) const dispatch = useAppDispatch() /** Download the current progress (i.e. what's saved in the browser store) */ const downloadProgress = (e) => { e.preventDefault() downloadFile({ data: JSON.stringify(gameProgress, null, 2), fileName: `lean4game-${gameId}-${new Date().toLocaleDateString()}.json`, fileType: 'text/json', }) } const eraseProgress = () => { dispatch(deleteProgress({game: gameId})) handleClose() } const downloadAndErase = (e) => { downloadProgress(e) eraseProgress() } return

Delete Progress?

Do you want to delete your saved progress irreversibly?

(This deletes your proofs and your collected inventory. Saves from other games are not deleted.)

} function UploadPopup ({handleClose}) { const [file, setFile] = React.useState(); const gameId = React.useContext(GameIdContext) const gameProgress = useSelector(selectProgress(gameId)) const dispatch = useAppDispatch() const handleFileChange = (e) => { if (e.target.files) { setFile(e.target.files[0]) } } /** Upload progress from a */ const uploadProgress = (e) => { if (!file) {return} const fileReader = new FileReader() fileReader.readAsText(file, "UTF-8") fileReader.onload = (e) => { const data = JSON.parse(e.target.result.toString()) as GameProgressState console.debug("Json Data", data) dispatch(loadProgress({game: gameId, data: data})) } handleClose() } /** Download the current progress (i.e. what's saved in the browser store) */ const downloadProgress = (e) => { e.preventDefault() downloadFile({ data: JSON.stringify(gameProgress, null, 2), fileName: `lean4game-${gameId}-${new Date().toLocaleDateString()}.json`, fileType: 'text/json', }) } return

Upload Saved Progress

Select a JSON file with the saved game progress to load your progress.

Warning: This will delete your current game progress! Consider downloading your current progress first!

} /** main page of the game showing amoung others the tree of worlds/levels */ function Welcome() { const gameId = React.useContext(GameIdContext) const {mobile, pageNumber, setPageNumber} = React.useContext(MobileContext) const gameInfo = useGetGameInfoQuery({game: gameId}) const inventory = useLoadInventoryOverviewQuery({game: gameId}) // impressum pop-up const [impressum, setImpressum] = React.useState(false) function closeImpressum() {setImpressum(false)} function toggleImpressum() {setImpressum(!impressum)} const [info, setInfo] = React.useState(false) function closeInfo() {setInfo(false)} function toggleInfo() {setInfo(!impressum)} /* state variables to toggle the pop-up menus */ const [eraseMenu, setEraseMenu] = React.useState(false); const openEraseMenu = () => setEraseMenu(true); const closeEraseMenu = () => setEraseMenu(false); const [uploadMenu, setUploadMenu] = React.useState(false); const openUploadMenu = () => setUploadMenu(true); const closeUploadMenu = () => setUploadMenu(false); // set the window title useEffect(() => { if (gameInfo.data?.title) { window.document.title = gameInfo.data.title } }, [gameInfo.data?.title]) return gameInfo.isLoading ? : <>
{ mobile ?
{(pageNumber == 0 ? : pageNumber == 1 ? : )}
: }
{impressum ? : null} {eraseMenu? : null} {uploadMenu? : null} {info ? : null} } export default Welcome