|
|
|
@ -1,14 +1,27 @@
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @fileOverview Define the menu displayed with the tree of worlds on the welcome page
|
|
|
|
|
|
|
|
*/
|
|
|
|
import * as React from 'react'
|
|
|
|
import * as React from 'react'
|
|
|
|
import { useStore, useSelector } from 'react-redux';
|
|
|
|
import { useStore, useSelector } from 'react-redux';
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
|
|
import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons'
|
|
|
|
import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import './world_selection_menu.css'
|
|
|
|
|
|
|
|
|
|
|
|
import { Button } from './button'
|
|
|
|
import { Button } from './button'
|
|
|
|
import { GameIdContext } from '../app';
|
|
|
|
import { GameIdContext } from '../app';
|
|
|
|
import { useAppDispatch, useAppSelector } from '../hooks';
|
|
|
|
import { useAppDispatch, useAppSelector } from '../hooks';
|
|
|
|
import { deleteProgress, selectProgress, loadProgress, GameProgressState } from '../state/progress';
|
|
|
|
import { deleteProgress, selectProgress, loadProgress, GameProgressState } from '../state/progress';
|
|
|
|
|
|
|
|
|
|
|
|
const downloadFile = ({ data, fileName, fileType }) => {
|
|
|
|
/** Only to specify the types for `downloadFile` */
|
|
|
|
|
|
|
|
interface downloadFileParam {
|
|
|
|
|
|
|
|
data: string
|
|
|
|
|
|
|
|
fileName: string
|
|
|
|
|
|
|
|
fileType: string
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Download a file containing `data` */
|
|
|
|
|
|
|
|
const downloadFile = ({ data, fileName, fileType } : downloadFileParam) => {
|
|
|
|
const blob = new Blob([data], { type: fileType })
|
|
|
|
const blob = new Blob([data], { type: fileType })
|
|
|
|
const a = document.createElement('a')
|
|
|
|
const a = document.createElement('a')
|
|
|
|
a.download = fileName
|
|
|
|
a.download = fileName
|
|
|
|
@ -22,25 +35,25 @@ const downloadFile = ({ data, fileName, fileType }) => {
|
|
|
|
a.remove()
|
|
|
|
a.remove()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function GameMenu() {
|
|
|
|
/** The menu that is shown next to the world selection graph */
|
|
|
|
|
|
|
|
function WorldSelectionMenu() {
|
|
|
|
const [file, setFile] = React.useState<File>();
|
|
|
|
const [file, setFile] = React.useState<File>();
|
|
|
|
|
|
|
|
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const gameId = React.useContext(GameIdContext)
|
|
|
|
const store = useStore()
|
|
|
|
const store = useStore()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* state variables to toggle the pop-up menus */
|
|
|
|
const [eraseMenu, setEraseMenu] = React.useState(false);
|
|
|
|
const [eraseMenu, setEraseMenu] = React.useState(false);
|
|
|
|
const openEraseMenu = () => setEraseMenu(true);
|
|
|
|
const openEraseMenu = () => setEraseMenu(true);
|
|
|
|
const closeEraseMenu = () => setEraseMenu(false);
|
|
|
|
const closeEraseMenu = () => setEraseMenu(false);
|
|
|
|
|
|
|
|
|
|
|
|
const [uploadMenu, setUploadMenu] = React.useState(false);
|
|
|
|
const [uploadMenu, setUploadMenu] = React.useState(false);
|
|
|
|
const openUploadMenu = () => setUploadMenu(true);
|
|
|
|
const openUploadMenu = () => setUploadMenu(true);
|
|
|
|
const closeUploadMenu = () => setUploadMenu(false);
|
|
|
|
const closeUploadMenu = () => setUploadMenu(false);
|
|
|
|
|
|
|
|
|
|
|
|
const gameProgress = useSelector(selectProgress(gameId))
|
|
|
|
const gameProgress = useSelector(selectProgress(gameId))
|
|
|
|
|
|
|
|
|
|
|
|
const dispatch = useAppDispatch()
|
|
|
|
const dispatch = useAppDispatch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Download the current progress (i.e. what's saved in the browser store) */
|
|
|
|
const downloadProgress = (e) => {
|
|
|
|
const downloadProgress = (e) => {
|
|
|
|
e.preventDefault()
|
|
|
|
e.preventDefault()
|
|
|
|
downloadFile({
|
|
|
|
downloadFile({
|
|
|
|
@ -48,29 +61,24 @@ function GameMenu() {
|
|
|
|
fileName: `lean4game-${gameId}-${new Date().toLocaleDateString()}.json`,
|
|
|
|
fileName: `lean4game-${gameId}-${new Date().toLocaleDateString()}.json`,
|
|
|
|
fileType: 'text/json',
|
|
|
|
fileType: 'text/json',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleFileChange = (e) => {
|
|
|
|
const handleFileChange = (e) => {
|
|
|
|
if (e.target.files) {
|
|
|
|
if (e.target.files) {
|
|
|
|
setFile(e.target.files[0]);
|
|
|
|
setFile(e.target.files[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const uploadProgress = (e) => {
|
|
|
|
|
|
|
|
if (!file) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const fileReader = new FileReader();
|
|
|
|
/** Upload progress from a */
|
|
|
|
fileReader.readAsText(file, "UTF-8");
|
|
|
|
const uploadProgress = (e) => {
|
|
|
|
|
|
|
|
if (!file) {return}
|
|
|
|
|
|
|
|
const fileReader = new FileReader()
|
|
|
|
|
|
|
|
fileReader.readAsText(file, "UTF-8")
|
|
|
|
fileReader.onload = (e) => {
|
|
|
|
fileReader.onload = (e) => {
|
|
|
|
const data = JSON.parse(e.target.result.toString()) as GameProgressState;
|
|
|
|
const data = JSON.parse(e.target.result.toString()) as GameProgressState
|
|
|
|
console.debug("Json Data", data);
|
|
|
|
console.debug("Json Data", data)
|
|
|
|
|
|
|
|
|
|
|
|
dispatch(loadProgress({game: gameId, data: data}))
|
|
|
|
dispatch(loadProgress({game: gameId, data: data}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
closeUploadMenu()
|
|
|
|
closeUploadMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -84,11 +92,10 @@ function GameMenu() {
|
|
|
|
eraseProgress()
|
|
|
|
eraseProgress()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return <nav className="game-menu">
|
|
|
|
return <nav className="world-selection-menu">
|
|
|
|
<Button onClick={downloadProgress} title="Download game progress" to=""><FontAwesomeIcon icon={faDownload} /></Button>
|
|
|
|
<Button onClick={downloadProgress} title="Download game progress" to=""><FontAwesomeIcon icon={faDownload} /></Button>
|
|
|
|
<Button title="Load game progress from JSON" onClick={openUploadMenu} to=""><FontAwesomeIcon icon={faUpload} /></Button>
|
|
|
|
<Button title="Load game progress from JSON" onClick={openUploadMenu} to=""><FontAwesomeIcon icon={faUpload} /></Button>
|
|
|
|
<Button title="Clear game progress" to="" onClick={openEraseMenu}><FontAwesomeIcon icon={faEraser} /></Button>
|
|
|
|
<Button title="Clear game progress" to="" onClick={openEraseMenu}><FontAwesomeIcon icon={faEraser} /></Button>
|
|
|
|
|
|
|
|
|
|
|
|
{eraseMenu?
|
|
|
|
{eraseMenu?
|
|
|
|
<div className="modal-wrapper">
|
|
|
|
<div className="modal-wrapper">
|
|
|
|
<div className="modal-backdrop" onClick={closeEraseMenu} />
|
|
|
|
<div className="modal-backdrop" onClick={closeEraseMenu} />
|
|
|
|
@ -105,7 +112,6 @@ function GameMenu() {
|
|
|
|
<Button onClick={closeEraseMenu} to="">Cancel</Button>
|
|
|
|
<Button onClick={closeEraseMenu} to="">Cancel</Button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div> : null}
|
|
|
|
</div> : null}
|
|
|
|
|
|
|
|
|
|
|
|
{uploadMenu ?
|
|
|
|
{uploadMenu ?
|
|
|
|
<div className="modal-wrapper">
|
|
|
|
<div className="modal-wrapper">
|
|
|
|
<div className="modal-backdrop" onClick={closeUploadMenu} />
|
|
|
|
<div className="modal-backdrop" onClick={closeUploadMenu} />
|
|
|
|
@ -126,4 +132,4 @@ function GameMenu() {
|
|
|
|
</nav>
|
|
|
|
</nav>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default GameMenu
|
|
|
|
export default WorldSelectionMenu
|