import * as React from 'react'; import { useEffect, useState, useRef } from 'react'; import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; import '@fontsource/roboto/500.css'; import '@fontsource/roboto/700.css'; import ReactMarkdown from 'react-markdown'; import { MathJax } from "better-react-mathjax"; import { Link as RouterLink } from 'react-router-dom'; import { Box, Button, CircularProgress, FormControlLabel, FormGroup, Switch } from '@mui/material'; import Grid from '@mui/material/Unstable_Grid2'; import LeftPanel from './LeftPanel'; import { LeanTaskGutter } from 'lean4web/client/src/editor/taskgutter'; import { AbbreviationProvider } from 'lean4web/client/src/editor/abbreviation/AbbreviationProvider'; import { AbbreviationRewriter } from 'lean4web/client/src/editor/abbreviation/rewriter/AbbreviationRewriter'; import { InfoProvider } from 'lean4web/client/src/editor/infoview'; import 'lean4web/client/src/editor/infoview.css' import { renderInfoview } from '@leanprover/infoview' import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js' import './level.css' import { ConnectionContext } from '../connection'; import Infoview from './Infoview'; import { useParams } from 'react-router-dom'; import { useLoadLevelQuery } from '../game/api'; function Level() { const params = useParams(); const levelId = parseInt(params.levelId) const worldId = params.worldId const [expertInfoview, setExpertInfoview] = useState(false) const codeviewRef = useRef(null) const infoviewRef = useRef(null) const messagePanelRef = useRef(null) useEffect(() => { // Scroll to top when loading a new level messagePanelRef.current!.scrollTo(0,0) }, [levelId]) const connection = React.useContext(ConnectionContext) const level = useLoadLevelQuery({world: worldId, level: levelId}) const {editor, infoProvider} = useLevelEditor(worldId, levelId, codeviewRef, infoviewRef) return <>
{level?.data?.introduction}

Aufgabe:

{level?.data?.descrText}
{level?.data?.descrFormat}
{ setExpertInfoview(!expertInfoview) }} control={} label="Expert mode" />
} export default Level function useLevelEditor(worldId: string, levelId: number, codeviewRef, infoviewRef) { const connection = React.useContext(ConnectionContext) const [editor, setEditor] = useState(null) const [infoProvider, setInfoProvider] = useState(null) const [infoviewApi, setInfoviewApi] = useState(null) // Create Editor useEffect(() => { const editor = monaco.editor.create(codeviewRef.current!, { glyphMargin: true, lightbulb: { enabled: true }, unicodeHighlight: { ambiguousCharacters: false, }, automaticLayout: true, minimap: { enabled: false }, lineNumbersMinChars: 3, 'semanticHighlighting.enabled': true, theme: 'vs-code-theme-converted' }) const infoProvider = new InfoProvider(connection.getLeanClient()) const div: HTMLElement = infoviewRef.current! const infoviewApi = renderInfoview(infoProvider.getApi(), div) setEditor(editor) setInfoProvider(infoProvider) setInfoviewApi(infoviewApi) return () => { editor.setModel(null); infoProvider.dispose(); } }, []) // Create model when level changes useEffect(() => { connection.startLeanClient().then((leanClient) => { if (editor) { const uri = monaco.Uri.parse(`file:///${worldId}/${levelId}`) const model = monaco.editor.getModel(uri) ?? monaco.editor.createModel('', 'lean4', uri) editor.setModel(model) infoviewApi.serverRestarted(leanClient.initializeResult) infoProvider.openPreview(editor, infoviewApi) new LeanTaskGutter(infoProvider.client, editor) new AbbreviationRewriter(new AbbreviationProvider(), model, editor) } }) }, [editor, levelId, connection]) return {editor, infoProvider} }