add menu to delete game progress

pull/79/head
Jon Eugster 3 years ago
parent 9514e558ad
commit a52f10ab11

@ -0,0 +1,60 @@
import * as React from 'react'
import { Button } from './Button'
import { GameIdContext } from '../App';
import { useStore } from 'react-redux';
import { useAppDispatch, useAppSelector } from '../hooks';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons'
import { deleteProgress } from '../state/progress';
function GameMenu() {
const gameId = React.useContext(GameIdContext)
const store = useStore()
const [eraseMenu, setEraseMenu] = React.useState(false);
const openEraseMenu = () => setEraseMenu(true);
const closeEraseMenu = () => setEraseMenu(false);
const dispatch = useAppDispatch()
const downloadProgress = () => {};
// const uploadProgress = () => {};
const eraseProgress = () => {
dispatch(deleteProgress({game: gameId}))
closeEraseMenu()
}
const downloadAndErase = () => {
downloadProgress ()
eraseProgress()
}
return <nav className="game-menu">
<Button disabled={true} onClick={downloadProgress} title="Download game progress" to=""><FontAwesomeIcon icon={faDownload} /></Button>
<Button disabled={true} title="Load game progress from JSON" to=""><FontAwesomeIcon icon={faUpload} /></Button>
<Button title="Clear game progress" to="" onClick={openEraseMenu}><FontAwesomeIcon icon={faEraser} /></Button>
{eraseMenu?
<div className="modal-wrapper">
<div className="modal-backdrop" onClick={closeEraseMenu} />
<div className="modal">
<div className="codicon codicon-close modal-close" onClick={closeEraseMenu}></div>
<h2>Delete Progress?</h2>
<p>Do you want to delete your saved state irreversibly?</p>
<p>(This only affects your saved proofs, no levels are ever locked.
Saves from other games are not deleted.)</p>
<Button onClick={eraseProgress} to="">Delete</Button>
<Button disabled={true} onClick={downloadAndErase} to="">Download & Delete</Button>
<Button onClick={closeEraseMenu} to="">Cancel</Button>
</div>
</div> : null}
</nav>
}
export default GameMenu

@ -7,6 +7,7 @@ import { useNavigate } from 'react-router-dom';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import Split from 'react-split' import Split from 'react-split'
import GameMenu from './GameMenu';
import {PrivacyPolicy} from './PrivacyPolicy'; import {PrivacyPolicy} from './PrivacyPolicy';
cytoscape.use( klay ); cytoscape.use( klay );
@ -17,6 +18,11 @@ import { Link } from 'react-router-dom';
import Markdown from './Markdown'; import Markdown from './Markdown';
import { selectCompleted } from '../state/progress'; import { selectCompleted } from '../state/progress';
import { GameIdContext } from '../App'; import { GameIdContext } from '../App';
import { Button } from './Button';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons'
const N = 24 // max number of levels per world const N = 24 // max number of levels per world
const R = 800 // radius of a world const R = 800 // radius of a world
@ -33,7 +39,7 @@ function LevelIcon({ worldId, levelId, position }) {
// TODO: relative positioning? // TODO: relative positioning?
return ( return (
<Link to={`/game/${gameId}/world/${worldId}/level/${levelId}`} key={`/game/${gameId}/world/${worldId}/level/${levelId}`}> <Link to={`/game/${gameId}/world/${worldId}/level/${levelId}`}>
<circle fill={completed ? "green" :"#999"} cx={x} cy={y} r={r} /> <circle fill={completed ? "green" :"#999"} cx={x} cy={y} r={r} />
</Link> </Link>
) )
@ -69,7 +75,9 @@ function Welcome() {
for (let i = 1; i <= gameInfo.data.worldSize[id]; i++) { for (let i = 1; i <= gameInfo.data.worldSize[id]; i++) {
svgElements.push( svgElements.push(
<LevelIcon position={position} worldId={id} levelId={i} /> <LevelIcon
key={`/game/${gameId}/world/${id}/level/${i}`}
position={position} worldId={id} levelId={i} />
) )
} }
@ -103,6 +111,7 @@ function Welcome() {
</Typography> </Typography>
</div> </div>
<div className="column"> <div className="column">
<GameMenu />
<Box textAlign='center' sx={{ m: 5 }}> <Box textAlign='center' sx={{ m: 5 }}>
<svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" <svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox={bounds ? `${s*bounds.x1 - padding} ${s*bounds.y1 - padding} ${s*bounds.x2 - s*bounds.x1 + 2 * padding} ${s*bounds.y2 - s*bounds.y1 + 2 * padding}` : ''}> viewBox={bounds ? `${s*bounds.x1 - padding} ${s*bounds.y1 - padding} ${s*bounds.x2 - s*bounds.x1 + 2 * padding} ${s*bounds.y2 - s*bounds.y1 + 2 * padding}` : ''}>
@ -112,7 +121,7 @@ function Welcome() {
</div> </div>
</Split> </Split>
} }
<PrivacyPolicy/> <PrivacyPolicy />
</div> </div>
} }

@ -191,3 +191,15 @@ svg .world-title {
.modal table { .modal table {
width: 100%; width: 100%;
} }
.game-menu {
padding: .5em;
}
.game-menu .btn {
min-width: 5em;
text-align: center;
margin-left: .4em;
margin-right: .4em;
margin-bottom: .2em;
}

@ -49,6 +49,9 @@ export const progressSlice = createSlice({
addLevelProgress(state, action) addLevelProgress(state, action)
state.level[action.payload.game][action.payload.world][action.payload.level].completed = true state.level[action.payload.game][action.payload.world][action.payload.level].completed = true
}, },
deleteProgress(state, action: PayloadAction<{game: string}>) {
state.level[action.payload.game] = {}
},
} }
}) })
@ -85,4 +88,4 @@ export function selectProgress() {
} }
} }
export const { changedSelection, codeEdited, levelCompleted } = progressSlice.actions export const { changedSelection, codeEdited, levelCompleted, deleteProgress } = progressSlice.actions

Loading…
Cancel
Save