force editor mode if template present

pull/120/head
joneugster 3 years ago
parent 04038a32c8
commit 047c5ae268

@ -281,7 +281,7 @@ export function WelcomeAppBar({gameInfo, toggleImpressum, openEraseMenu, openUpl
/** The top-navigation bar */ /** The top-navigation bar */
export function LevelAppBar({ export function LevelAppBar({
isLoading, levelTitle, impressum, toggleImpressum, isLoading, levelTitle, impressum, toggleImpressum,
pageNumber = undefined, setPageNumber = undefined}) { pageNumber = undefined, setPageNumber = undefined, lockEditorMode=false}) {
const gameId = React.useContext(GameIdContext) const gameId = React.useContext(GameIdContext)
const {worldId, levelId} = React.useContext(WorldLevelIdContext) const {worldId, levelId} = React.useContext(WorldLevelIdContext)
const gameInfo = useGetGameInfoQuery({game: gameId}) const gameInfo = useGetGameInfoQuery({game: gameId})
@ -295,6 +295,13 @@ export function LevelAppBar({
const [navOpen, setNavOpen] = React.useState(false) const [navOpen, setNavOpen] = React.useState(false)
function toggleEditor(ev) {
if (!lockEditorMode){
setTypewriterMode(!typewriterMode)
setNavOpen(false)
}
}
return <div className="app-bar" style={isLoading ? {display: "none"} : null} > return <div className="app-bar" style={isLoading ? {display: "none"} : null} >
{mobile ? {mobile ?
<> <>
@ -388,9 +395,9 @@ export function LevelAppBar({
<FontAwesomeIcon icon={faHome} />&nbsp;Leave World <FontAwesomeIcon icon={faHome} />&nbsp;Leave World
</Button> </Button>
} }
<Button className="btn btn-inverted toggle-width" disabled={levelId <= 0} inverted="true" to="" <Button className="btn btn-inverted toggle-width" disabled={levelId <= 0 || lockEditorMode} inverted="true" to=""
onClick={(ev) => { setTypewriterMode(!typewriterMode); setNavOpen(false) }} onClick={(ev) => toggleEditor(ev)}
title={typewriterMode ? "Editor mode" : "Typewriter mode"}> title={lockEditorMode ? "Editor mode is enforced!" : typewriterMode ? "Editor mode" : "Typewriter mode"}>
<FontAwesomeIcon icon={typewriterMode ? faCode : faTerminal} /> <FontAwesomeIcon icon={typewriterMode ? faCode : faTerminal} />
</Button> </Button>
<Button className="btn btn-inverted toggle-width" title="information, Impressum, privacy policy" inverted="true" to="" onClick={(ev) => {toggleImpressum(ev); setNavOpen(false)}}> <Button className="btn btn-inverted toggle-width" title="information, Impressum, privacy policy" inverted="true" to="" onClick={(ev) => {toggleImpressum(ev); setNavOpen(false)}}>

@ -21,13 +21,13 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import { GameIdContext } from '../../app'; import { GameIdContext } from '../../app';
import { useAppDispatch, useAppSelector } from '../../hooks'; import { useAppDispatch, useAppSelector } from '../../hooks';
import { LevelInfo } from '../../state/api'; import { LevelInfo } from '../../state/api';
import { changedInventory, levelCompleted, selectCompleted, selectInventory } from '../../state/progress'; import { changedInventory, levelCompleted, selectCode, selectCompleted, selectInventory } from '../../state/progress';
import Markdown from '../markdown'; import Markdown from '../markdown';
import { Infos } from './infos'; import { Infos } from './infos';
import { AllMessages, Errors, WithLspDiagnosticsContext } from './messages'; import { AllMessages, Errors, WithLspDiagnosticsContext } from './messages';
import { Goal } from './goals'; import { Goal } from './goals';
import { DeletedChatContext, InputModeContext, MobileContext, MonacoEditorContext, ProofContext, ProofStep, SelectionContext } from './context'; import { DeletedChatContext, InputModeContext, MobileContext, MonacoEditorContext, ProofContext, ProofStep, SelectionContext, WorldLevelIdContext } from './context';
import { Typewriter, hasErrors, hasInteractiveErrors } from './typewriter'; import { Typewriter, hasErrors, hasInteractiveErrors } from './typewriter';
import { InteractiveDiagnostic } from '@leanprover/infoview/*'; import { InteractiveDiagnostic } from '@leanprover/infoview/*';
import { Button } from '../button'; import { Button } from '../button';
@ -116,7 +116,7 @@ function DualEditorMain({ worldId, levelId, level, worldSize }: { worldId: strin
{typewriterMode ? {typewriterMode ?
<TypewriterInterface world={worldId} level={levelId} data={level} worldSize={worldSize}/> <TypewriterInterface world={worldId} level={levelId} data={level} worldSize={worldSize}/>
: :
<Main key={`${worldId}/${levelId}`} world={worldId} level={levelId} /> <Main key={`${worldId}/${levelId}`} world={worldId} level={levelId} data={level} />
} }
</ProgressContext.Provider> </ProgressContext.Provider>
</WithLspDiagnosticsContext> </WithLspDiagnosticsContext>
@ -141,12 +141,24 @@ function ExerciseStatement({ data }) {
// TODO: This is only used in `EditorInterface` // TODO: This is only used in `EditorInterface`
// while `TypewriterInterface` has this copy-pasted in. // while `TypewriterInterface` has this copy-pasted in.
export function Main(props: { world: string, level: number }) { export function Main(props: { world: string, level: number, data: LevelInfo}) {
const ec = React.useContext(EditorContext); const ec = React.useContext(EditorContext);
const gameId = React.useContext(GameIdContext) const gameId = React.useContext(GameIdContext)
const {worldId, levelId} = React.useContext(WorldLevelIdContext)
const completed = useAppSelector(selectCompleted(gameId, props.world, props.level)) const completed = useAppSelector(selectCompleted(gameId, props.world, props.level))
console.debug(`template: ${props.data.template}`)
// React.useEffect (() => {
// if (props.data.template) {
// let code: string = selectCode(gameId, worldId, levelId)(store.getState())
// if (!code.length) {
// //models.push(monaco.editor.createModel(code, 'lean4', uri))
// }
// }
// }, [props.data.template])
/* Set up updates to the global infoview state on editor events. */ /* Set up updates to the global infoview state on editor events. */
const config = useEventResult(ec.events.changedInfoviewConfig) ?? defaultInfoviewConfig; const config = useEventResult(ec.events.changedInfoviewConfig) ?? defaultInfoviewConfig;

@ -252,6 +252,25 @@ function PlayableLevel({impressum, setImpressum}) {
const {editor, infoProvider, editorConnection} = const {editor, infoProvider, editorConnection} =
useLevelEditor(codeviewRef, initialCode, initialSelections, onDidChangeContent, onDidChangeSelection) useLevelEditor(codeviewRef, initialCode, initialSelections, onDidChangeContent, onDidChangeSelection)
useEffect (() => {
// Lock editor mode
if (level?.data?.template) {
setTypewriterMode(false)
console.debug(`inserting template: ${level.data.template}`)
// // TODO: This does not work! HERE
// // Probably overwritten by a query to the server
// editor.executeEdits("command-line", [{
// range: editor.getModel().getFullModelRange(),
// text: level.data.template,
// forceMoveMarkers: false
// }])
} else {
setTypewriterMode(true)
}
}, [level, levelId, worldId, gameId])
/** Unused. Was implementing an undo button, which has been replaced by `deleteProof` inside /** Unused. Was implementing an undo button, which has been replaced by `deleteProof` inside
* `TypewriterInterface`. * `TypewriterInterface`.
*/ */
@ -355,6 +374,7 @@ function PlayableLevel({impressum, setImpressum}) {
<MonacoEditorContext.Provider value={editor}> <MonacoEditorContext.Provider value={editor}>
<LevelAppBar <LevelAppBar
isLoading={level.isLoading} isLoading={level.isLoading}
lockEditorMode={level.data?.template !== null}
levelTitle={`${mobile ? '' : 'Level '}${levelId} / ${gameInfo.data?.worldSize[worldId]}` + levelTitle={`${mobile ? '' : 'Level '}${levelId} / ${gameInfo.data?.worldSize[worldId]}` +
(level?.data?.title && ` : ${level?.data?.title}`)} (level?.data?.title && ` : ${level?.data?.title}`)}
impressum={impressum} impressum={impressum}

@ -96,6 +96,7 @@ partial def findForbiddenTactics (inputCtx : Parser.InputContext)
for n in ns do for n in ns do
let some (.thmInfo ..) := (← getEnv).find? n let some (.thmInfo ..) := (← getEnv).find? n
| return () -- not a theroem -> ignore | return () -- not a theroem -> ignore
-- TODO: Filter thhe theorem we want to proof to avoid structural recursion!
let lemmasAndDefs := levelParams.lemmas ++ levelParams.definitions let lemmasAndDefs := levelParams.lemmas ++ levelParams.definitions
match lemmasAndDefs.find? (fun l => l.name == n) with match lemmasAndDefs.find? (fun l => l.name == n) with
| none => addWarningMessage info s!"You have not unlocked the lemma/definition '{n}' yet!" | none => addWarningMessage info s!"You have not unlocked the lemma/definition '{n}' yet!"

Loading…
Cancel
Save