diff --git a/client/src/components/Level.tsx b/client/src/components/Level.tsx index 9a3f6cf..4908a9f 100644 --- a/client/src/components/Level.tsx +++ b/client/src/components/Level.tsx @@ -29,7 +29,7 @@ import { useStore } from 'react-redux'; import { EditorContext, ConfigContext, ProgressContext, VersionContext } from '../../../node_modules/lean4-infoview/src/infoview/contexts'; import { EditorConnection, EditorEvents } from '../../../node_modules/lean4-infoview/src/infoview/editorConnection'; import { EventEmitter } from '../../../node_modules/lean4-infoview/src/infoview/event'; -import { Main, EditorInterface } from './infoview/main' +import { EditorInterface, ReducedInterface } from './infoview/main' import type { Location } from 'vscode-languageserver-protocol'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' @@ -97,13 +97,6 @@ function ExerciseStatement({data}) { } -function ReducedInterface({worldId, levelId, editorConnection}) { - return
- {/* */} - {editorConnection &&
} -
-} - function PlayableLevel({worldId, levelId}) { const codeviewRef = useRef(null) const chatPanelRef = useRef(null) @@ -280,17 +273,16 @@ function PlayableLevel({worldId, levelId}) {
- {/* We need the editor to be hidden because the command line edits its content */} + {/* We need the editor to always there and hidden because + the command line edits its content */}
- {/*
- {commandLineMode && } -
*/} - {/* {editorConnection &&
} */} diff --git a/client/src/components/infoview/main.tsx b/client/src/components/infoview/main.tsx index e90eff6..5ffa88a 100644 --- a/client/src/components/infoview/main.tsx +++ b/client/src/components/infoview/main.tsx @@ -115,3 +115,87 @@ export function EditorInterface({data, codeviewRef, hidden, worldId, levelId, ed } + +export function ReducedInterface(props: {world: string, level: number}) { + + const ec = React.useContext(EditorContext); + const gameId = React.useContext(GameIdContext) + + const dispatch = useAppDispatch() + + // Mark level as completed when server gives notification + useServerNotificationEffect( + '$/game/completed', + (params: any) => { + + if (ec.events.changedCursorLocation.current && + ec.events.changedCursorLocation.current.uri === params.uri) { + dispatch(levelCompleted({game: gameId, world: props.world, level: props.level})) + } + }, + [] + ); + + const completed = useAppSelector(selectCompleted(gameId, props.world, props.level)) + + /* Set up updates to the global infoview state on editor events. */ + const config = useEventResult(ec.events.changedInfoviewConfig) ?? defaultInfoviewConfig; + + const [allProgress, _1] = useServerNotificationState( + '$/lean/fileProgress', + new Map(), + async (params: LeanFileProgressParams) => (allProgress) => { + const newProgress = new Map(allProgress); + return newProgress.set(params.textDocument.uri, params.processing); + }, + [] + ); + + const curUri = useEventResult(ec.events.changedCursorLocation, loc => loc?.uri); + + useClientNotificationEffect( + 'textDocument/didClose', + (params: DidCloseTextDocumentParams) => { + if (ec.events.changedCursorLocation.current && + ec.events.changedCursorLocation.current.uri === params.textDocument.uri) { + ec.events.changedCursorLocation.fire(undefined) + } + }, + [] + ); + + const serverVersion = + useEventResult(ec.events.serverRestarted, result => new ServerVersion(result.serverInfo?.version ?? '')) + const serverStoppedResult = useEventResult(ec.events.serverStopped); + // NB: the cursor may temporarily become `undefined` when a file is closed. In this case + // it's important not to reconstruct the `WithBlah` wrappers below since they contain state + // that we want to persist. + let ret + if (!serverVersion) { + ret =

Waiting for Lean server to start...

+ } else if (serverStoppedResult){ + ret =

{serverStoppedResult.message}

{serverStoppedResult.reason}

+ } else { + ret =
+ {completed &&
Level completed! 🎉
} + +
+ } + + return
+ {/* */} + + + + + + {ret} + + + + + +
+ + +}