pull/118/head
Jon Eugster 3 years ago
parent 205c484623
commit 0f9b0c7b18

@ -1,13 +1,17 @@
/* Mostly copied from https://github.com/leanprover/vscode-lean4/blob/master/lean4-infoview/src/infoview/goals.tsx */
/**
* @fileOverview
*
* Mostly copied from https://github.com/leanprover/vscode-lean4/blob/master/lean4-infoview/src/infoview/goals.tsx
*/
import * as React from 'react'
import { InteractiveCode } from '../../../../node_modules/lean4-infoview/src/infoview/interactiveCode'
import { InteractiveHypothesisBundle_nonAnonymousNames, MVarId, TaggedText_stripTags } from '@leanprover/infoview-api'
import { WithTooltipOnHover } from '../../../../node_modules/lean4-infoview/src/infoview/tooltips';
import { EditorContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts';
import { Locations, LocationsContext, SelectableLocation } from '../../../../node_modules/lean4-infoview/src/infoview/goalLocation';
import { InteractiveGoal, InteractiveGoals, InteractiveHypothesisBundle } from './rpc_api';
import { InteractiveCode } from '../../../../node_modules/lean4-infoview/src/infoview/interactiveCode'
import { WithTooltipOnHover } from '../../../../node_modules/lean4-infoview/src/infoview/tooltips';
import { InputModeContext } from './context';
import { InteractiveGoal, InteractiveGoals, InteractiveHypothesisBundle } from './rpc_api';
/** Returns true if `h` is inaccessible according to Lean's default name rendering. */

@ -83,7 +83,6 @@ function PlayableLevel({worldId, levelId}) {
const theme = useTheme();
useEffect(() => {
// Scroll to top when loading a new level
// TODO: Thats the wrong behaviour probably
@ -416,7 +415,9 @@ function useLevelEditor(worldId: string, levelId: number, codeviewRef, initialCo
editor.onDidChangeCursorSelection(() => onDidChangeSelection(editor.getSelections()))
editor.setModel(model)
if (initialSelections) {
editor.setSelections(initialSelections)
console.debug("Initial Selection: ", initialSelections)
// BUG: Somehow I get an `invalid arguments` bug here
// editor.setSelections(initialSelections)
}
infoviewApi.serverRestarted(leanClient.initializeResult)

@ -1,45 +1,52 @@
/**
* @fileOverview The impressum/privacy policy
*/
import { faShield } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as React from 'react'
function PrivacyPolicyPopup ({handleClose}) {
/** Pop-up that is displayed when opening the privacy policy.
*
* `handleClose` is the function to close it again because it's open/closed state is
* controlled by the containing element.
*/
function PrivacyPolicyPopup (handleClose) {
return <div className="modal-wrapper">
<div className="modal-backdrop" onClick={handleClose} />
<div className="modal">
<div className="codicon codicon-close modal-close" onClick={handleClose}></div>
<h2>Privacy Policy &amp; Impressum</h2>
<p>Our server collects metadata (such as IP address, browser, operating system)
<p>
Our server collects metadata (such as IP address, browser, operating system)
and the data that the user enters into the editor. The data is used to
compute the Lean output and display it to the user. The information will be stored
as long as the user stays on our website and will be deleted immediately afterwards.
We keep logs to improve our software, but the contained data is anonymized.</p>
<p>We do not use cookies, but your game progress is stored in the browser
We keep logs to improve our software, but the contained data is anonymized.
</p>
<p>
We do not use cookies, but your game progress is stored in the browser
as site data. Your game progress is not saved on the server; if you delete
your browser storage, it is completely gone.
</p>
<p>Our server is located in Germany.</p>
<p><strong>Contact information:</strong><br />
<p>
<strong>Contact information:</strong><br />
Jon Eugster<br />
Mathematisches Institut der Heinrich-Heine-Universität Düsseldorf<br />
Universitätsstr. 1<br />
40225 Düsseldorf<br />
Germany<br />
+49 211 81-12173<br />
<a href="https://www.math.hhu.de/en/lehrstuehle-/-personen-/-ansprechpartner/innen/lehrstuehle-des-mathematischen-instituts/lehrstuhl-fuer-algebraische-geometrie/team/jon-eugster">Contact Details</a>
</p>
</div>
</div>
}
const PrivacyPolicy: React.FC = () => {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const [open, setOpen] = React.useState(false)
const handleOpen = () => setOpen(true)
const handleClose = () => setOpen(false)
return (
<span>
<div className="privacy" onClick={handleOpen} title="Privacy Policy &amp; Impressum">
@ -47,15 +54,9 @@ const PrivacyPolicy: React.FC = () => {
<p className="p1">legal</p>
<p className="p2">notes</p>
</div>
{open?
<PrivacyPolicyPopup handleClose={handleClose} />: null}
{open ? <PrivacyPolicyPopup handleClose={handleClose} /> : null}
</span>
)
}
// export default PrivacyPolicy
export {
PrivacyPolicy,
PrivacyPolicyPopup,
}
export {PrivacyPolicy, PrivacyPolicyPopup}

@ -196,18 +196,6 @@ svg .world-title {
width: 100%;
}
.game-menu {
padding: .5em;
}
.game-menu .btn {
min-width: 5em;
text-align: center;
margin-left: .4em;
margin-right: .4em;
margin-bottom: .2em;
}
.modal a.download-link {
cursor: pointer;
font-style: italic;

@ -12,7 +12,7 @@ import { GameIdContext } from '../app';
import { selectCompleted } from '../state/progress';
import { useGetGameInfoQuery } from '../state/api';
import Markdown from './markdown';
import GameMenu from './game_menu';
import WorldSelectionMenu from './world_selection_menu';
import {PrivacyPolicy} from './privacy_policy';
cytoscape.use( klay );
@ -104,7 +104,7 @@ function Welcome() {
</Typography>
</div>
<div className="column">
<GameMenu />
<WorldSelectionMenu />
<Box textAlign='center' sx={{ m: 5 }}>
<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}` : ''}>

@ -0,0 +1,11 @@
.world-selection-menu {
padding: .5em;
}
.world-selection-menu .btn {
min-width: 5em;
text-align: center;
margin-left: .4em;
margin-right: .4em;
margin-bottom: .2em;
}

@ -1,14 +1,27 @@
/**
* @fileOverview Define the menu displayed with the tree of worlds on the welcome page
*/
import * as React from 'react'
import { useStore, useSelector } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons'
import './world_selection_menu.css'
import { Button } from './button'
import { GameIdContext } from '../app';
import { useAppDispatch, useAppSelector } from '../hooks';
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 a = document.createElement('a')
a.download = fileName
@ -22,25 +35,25 @@ const downloadFile = ({ data, fileName, fileType }) => {
a.remove()
}
function GameMenu() {
/** The menu that is shown next to the world selection graph */
function WorldSelectionMenu() {
const [file, setFile] = React.useState<File>();
const gameId = React.useContext(GameIdContext)
const store = useStore()
/* 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);
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({
@ -48,29 +61,24 @@ function GameMenu() {
fileName: `lean4game-${gameId}-${new Date().toLocaleDateString()}.json`,
fileType: 'text/json',
})
};
}
const handleFileChange = (e) => {
if (e.target.files) {
setFile(e.target.files[0]);
setFile(e.target.files[0])
}
};
const uploadProgress = (e) => {
if (!file) {
return;
}
const fileReader = new FileReader();
fileReader.readAsText(file, "UTF-8");
/** 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);
const data = JSON.parse(e.target.result.toString()) as GameProgressState
console.debug("Json Data", data)
dispatch(loadProgress({game: gameId, data: data}))
}
closeUploadMenu()
}
@ -84,11 +92,10 @@ function GameMenu() {
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 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>
{eraseMenu?
<div className="modal-wrapper">
<div className="modal-backdrop" onClick={closeEraseMenu} />
@ -105,7 +112,6 @@ function GameMenu() {
<Button onClick={closeEraseMenu} to="">Cancel</Button>
</div>
</div> : null}
{uploadMenu ?
<div className="modal-wrapper">
<div className="modal-backdrop" onClick={closeUploadMenu} />
@ -126,4 +132,4 @@ function GameMenu() {
</nav>
}
export default GameMenu
export default WorldSelectionMenu
Loading…
Cancel
Save