diff --git a/client/src/App.test.js b/client/src/app.test.js similarity index 89% rename from client/src/App.test.js rename to client/src/app.test.js index 1f03afe..888a926 100644 --- a/client/src/App.test.js +++ b/client/src/app.test.js @@ -1,5 +1,5 @@ import { render, screen } from '@testing-library/react'; -import App from './App'; +import App from './app'; test('renders learn react link', () => { render(); diff --git a/client/src/App.tsx b/client/src/app.tsx similarity index 82% rename from client/src/App.tsx rename to client/src/app.tsx index cf2787b..e995fac 100644 --- a/client/src/App.tsx +++ b/client/src/app.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { useState, useEffect } from 'react'; import { Outlet, useParams } from "react-router-dom"; import '@fontsource/roboto/300.css'; @@ -9,8 +8,7 @@ import '@fontsource/roboto/700.css'; import './reset.css'; import './app.css'; - -export const GameIdContext = React.createContext(undefined); +import { GameIdContext } from './components/infoview/context'; function App() { const params = useParams(); diff --git a/client/src/components/Button.tsx b/client/src/components/button.tsx similarity index 100% rename from client/src/components/Button.tsx rename to client/src/components/button.tsx diff --git a/client/src/ErrorPage.tsx b/client/src/components/error_page.tsx similarity index 100% rename from client/src/ErrorPage.tsx rename to client/src/components/error_page.tsx diff --git a/client/src/components/GameMenu.tsx b/client/src/components/game_menu.tsx similarity index 94% rename from client/src/components/GameMenu.tsx rename to client/src/components/game_menu.tsx index ab0d41b..87c10b1 100644 --- a/client/src/components/GameMenu.tsx +++ b/client/src/components/game_menu.tsx @@ -1,13 +1,11 @@ import * as React from 'react' -import { Button } from './Button' -import { GameIdContext } from '../App'; -import { useStore } from 'react-redux'; -import { useAppDispatch, useAppSelector } from '../hooks'; -import { useSelector } from 'react-redux'; - +import { useStore, useSelector } from 'react-redux'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons' +import { Button } from './button' +import { GameIdContext } from './infoview/context'; +import { useAppDispatch, useAppSelector } from '../state/hooks'; import { deleteProgress, selectProgress, loadProgress, GameProgressState } from '../state/progress'; const downloadFile = ({ data, fileName, fileType }) => { diff --git a/client/src/components/infoview/hints.tsx b/client/src/components/hints.tsx similarity index 78% rename from client/src/components/infoview/hints.tsx rename to client/src/components/hints.tsx index e97080c..90918f1 100644 --- a/client/src/components/infoview/hints.tsx +++ b/client/src/components/hints.tsx @@ -1,7 +1,6 @@ -import { GameHint } from "./rpcApi"; +import { GameHint } from "./infoview/rpc_api"; import * as React from 'react'; -import { Alert, FormControlLabel, Switch } from '@mui/material'; -import Markdown from '../Markdown'; +import Markdown from './markdown'; export function Hint({hint} : {hint: GameHint}) { return
{hint.text}
diff --git a/client/src/components/infoview/CommandLine.tsx b/client/src/components/infoview/command_line.tsx similarity index 96% rename from client/src/components/infoview/CommandLine.tsx rename to client/src/components/infoview/command_line.tsx index 72fa488..1c88a9b 100644 --- a/client/src/components/infoview/CommandLine.tsx +++ b/client/src/components/infoview/command_line.tsx @@ -1,24 +1,20 @@ import * as React from 'react' import { useRef, useState, useEffect } from 'react' -import { LspDiagnosticsContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts'; -import { useServerNotificationEffect } from '../../../../node_modules/lean4-infoview/src/infoview/util'; -import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js' -import { DiagnosticSeverity, PublishDiagnosticsParams } from 'vscode-languageserver-protocol'; -import { InputModeContext, MonacoEditorContext } from '../Level' - import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faWandMagicSparkles } from '@fortawesome/free-solid-svg-icons' -import { AbbreviationRewriter } from 'lean4web/client/src/editor/abbreviation/rewriter/AbbreviationRewriter'; -import { AbbreviationProvider } from 'lean4web/client/src/editor/abbreviation/AbbreviationProvider'; - +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js' import { Registry } from 'monaco-textmate' // peer dependency import { wireTmGrammars } from 'monaco-editor-textmate' -import * as lightPlusTheme from 'lean4web/client/src/lightPlus.json' +import { DiagnosticSeverity, PublishDiagnosticsParams } from 'vscode-languageserver-protocol'; +import { useServerNotificationEffect } from '../../../../node_modules/lean4-infoview/src/infoview/util'; +import { AbbreviationRewriter } from 'lean4web/client/src/editor/abbreviation/rewriter/AbbreviationRewriter'; +import { AbbreviationProvider } from 'lean4web/client/src/editor/abbreviation/AbbreviationProvider'; import * as leanSyntax from 'lean4web/client/src/syntaxes/lean.json' import * as leanMarkdownSyntax from 'lean4web/client/src/syntaxes/lean-markdown.json' import * as codeblockSyntax from 'lean4web/client/src/syntaxes/codeblock.json' import languageConfig from 'lean4/language-configuration.json'; +import { InputModeContext, MonacoEditorContext } from './context' /* We register a new language `leancmd` that looks like lean4, but does not use the lsp server. */ diff --git a/client/src/components/infoview/context.ts b/client/src/components/infoview/context.ts new file mode 100644 index 0000000..ccfd453 --- /dev/null +++ b/client/src/components/infoview/context.ts @@ -0,0 +1,77 @@ +/** + * @fileOverview This file contains the the react contexts used in the project. + */ +import * as React from 'react'; +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js' +import { InteractiveDiagnostic, InteractiveTermGoal } from '@leanprover/infoview-api'; +import { InteractiveGoals } from './rpc_api'; + +export const GameIdContext = React.createContext(undefined); + +export const MonacoEditorContext = React.createContext( + null as any) + +// TODO: Is this still used? +export const HintContext = React.createContext<{ + showHiddenHints : boolean, + setShowHiddenHints: React.Dispatch> +}>({ + showHiddenHints: true, + setShowHiddenHints: () => {}, +}); + +export type InfoStatus = 'updating' | 'error' | 'ready'; + +export type ProofStep = { + // TODO: Add correct types + command : string + goals: string + hints: string + errors: string +} + +export const ProofContext = React.createContext<{ + // The first entry will always have an empty/undefined command + proof: ProofStep[], + setProof: React.Dispatch>> +}>({ + proof: [], + setProof: () => {} +}) + +export interface ProofStateProps { + // pos: DocumentPosition; + status: InfoStatus; + messages: InteractiveDiagnostic[]; + goals?: InteractiveGoals; + termGoal?: InteractiveTermGoal; + error?: string; + // userWidgets: UserWidgetInstance[]; + // rpcSess: RpcSessionAtPos; + // triggerUpdate: () => Promise; +} + +export const ProofStateContext = React.createContext<{ + proofState : ProofStateProps, + setProofState: React.Dispatch> +}>({ + proofState : { + status: 'updating', + messages: [], + goals: undefined, + termGoal: undefined, + error: undefined}, + setProofState: () => {}, +}); + +export const InputModeContext = React.createContext<{ + commandLineMode: boolean, + setCommandLineMode: React.Dispatch>, + commandLineInput: string, + setCommandLineInput: React.Dispatch> +}>({ + commandLineMode: true, + setCommandLineMode: () => {}, + commandLineInput: "", + setCommandLineInput: () => {}, +}); diff --git a/client/src/components/infoview/goals.tsx b/client/src/components/infoview/goals.tsx index e83888c..a288a15 100644 --- a/client/src/components/infoview/goals.tsx +++ b/client/src/components/infoview/goals.tsx @@ -6,10 +6,9 @@ import { InteractiveHypothesisBundle_nonAnonymousNames, MVarId, TaggedText_strip 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 './rpcApi'; -import { Hints } from './hints'; -import { CommandLine } from './CommandLine'; -import { InputModeContext } from '../Level'; +import { InteractiveGoal, InteractiveGoals, InteractiveHypothesisBundle } from './rpc_api'; +import { InputModeContext } from './context'; + /** Returns true if `h` is inaccessible according to Lean's default name rendering. */ function isInaccessibleName(h: string): boolean { @@ -231,6 +230,7 @@ export const OtherGoals = React.memo((props: GoalProps2) => { }) + export const ProofDisplay = React.memo((props : ProofDisplayProps) => { const { proof } = props const steps = proof.match(/.+/g) diff --git a/client/src/components/infoview/info.tsx b/client/src/components/infoview/info.tsx index c57621b..1b87255 100644 --- a/client/src/components/infoview/info.tsx +++ b/client/src/components/infoview/info.tsx @@ -1,24 +1,25 @@ /* Mostly copied from https://github.com/leanprover/vscode-lean4/blob/master/lean4-infoview/src/infoview/info.tsx */ import * as React from 'react'; +import { CircularProgress } from '@mui/material'; + + import type { Location, Diagnostic } from 'vscode-languageserver-protocol'; -import { goalsToString, Goal, MainAssumptions, OtherGoals, FilteredGoals, ProofDisplay } from './goals' -import { basename, DocumentPosition, RangeHelpers, useEvent, usePausableState, discardMethodNotFound, - mapRpcError, useAsyncWithTrigger, PausableProps } from '../../../../node_modules/lean4-infoview/src/infoview/util'; -import { ConfigContext, EditorContext, LspDiagnosticsContext, ProgressContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts'; -import { AllMessages, lspDiagToInteractive, MessagesList } from './messages'; import { getInteractiveTermGoal, InteractiveDiagnostic, UserWidgetInstance, Widget_getWidgets, RpcSessionAtPos, isRpcError, RpcErrorCode, getInteractiveDiagnostics, InteractiveTermGoal } from '@leanprover/infoview-api'; -import { InteractiveGoal, InteractiveGoals } from './rpcApi'; +import { basename, DocumentPosition, RangeHelpers, useEvent, usePausableState, discardMethodNotFound, + mapRpcError, useAsyncWithTrigger, PausableProps } from '../../../../node_modules/lean4-infoview/src/infoview/util'; +import { ConfigContext, EditorContext, LspDiagnosticsContext, ProgressContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts'; import { PanelWidgetDisplay } from '../../../../node_modules/lean4-infoview/src/infoview/userWidget' import { RpcContext, useRpcSessionAtPos } from '../../../../node_modules/lean4-infoview/src/infoview/rpcSessions'; import { GoalsLocation, Locations, LocationsContext } from '../../../../node_modules/lean4-infoview/src/infoview/goalLocation'; -import { InteractiveCode } from '../../../../node_modules/lean4-infoview/src/infoview/interactiveCode' -import { CircularProgress } from '@mui/material'; -import { InputModeContext, MonacoEditorContext, HintContext, ProofStateProps, InfoStatus, ProofStateContext } from '../Level' -import { Hint } from './hints'; + +import { AllMessages, lspDiagToInteractive, MessagesList } from './messages'; +import { goalsToString, Goal, MainAssumptions, OtherGoals, FilteredGoals, ProofDisplay } from './goals' +import { InteractiveGoal, InteractiveGoals } from './rpc_api'; +import { InputModeContext, MonacoEditorContext, HintContext, ProofStateProps, InfoStatus, ProofStateContext } from './context' type InfoKind = 'cursor' | 'pin'; @@ -127,7 +128,7 @@ const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => {
{ goals && goals.goals.length > 0 && <> - {/* */} + }
diff --git a/client/src/components/infoview/infoview.css b/client/src/components/infoview/infoview.css index 1024033..9aa5fd2 100644 --- a/client/src/components/infoview/infoview.css +++ b/client/src/components/infoview/infoview.css @@ -64,7 +64,7 @@ flex-direction: column; } -.command-line .command-line-input{ +.command-line .command-line-input { flex: 1; } @@ -128,3 +128,14 @@ border-radius: 1em; padding: 0.6em; } + + +/* Push the goals to the bottom for now, until we insert the proof history above. */ +.commandline-interface .content { + display: flex; + flex-direction: column; +} + +.commandline-interface .content .tmp-pusher { + flex: 1; +} diff --git a/client/src/components/infoview/main.tsx b/client/src/components/infoview/main.tsx index 38e520b..d385ff5 100644 --- a/client/src/components/infoview/main.tsx +++ b/client/src/components/infoview/main.tsx @@ -4,26 +4,28 @@ import * as React from 'react'; import type { DidCloseTextDocumentParams, DidChangeTextDocumentParams, Location, DocumentUri } from 'vscode-languageserver-protocol'; import 'tachyons/css/tachyons.css'; -// import '@vscode/codicons/dist/codicon.ttf'; import '@vscode/codicons/dist/codicon.css'; import '../../../../node_modules/lean4-infoview/src/infoview/index.css'; import './infoview.css' import { LeanFileProgressParams, LeanFileProgressProcessingInfo, defaultInfoviewConfig, EditorApi, InfoviewApi } from '@leanprover/infoview-api'; - -import { Infos } from './infos'; -import { AllMessages, WithLspDiagnosticsContext } from './messages'; import { useClientNotificationEffect, useServerNotificationEffect, useEventResult, useServerNotificationState } from '../../../../node_modules/lean4-infoview/src/infoview/util'; import { EditorContext, ConfigContext, ProgressContext, VersionContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts'; import { WithRpcSessions } from '../../../../node_modules/lean4-infoview/src/infoview/rpcSessions'; import { ServerVersion } from '../../../../node_modules/lean4-infoview/src/infoview/serverVersion'; -import { useAppDispatch, useAppSelector } from '../../hooks'; -import { levelCompleted, selectCompleted } from '../../state/progress'; -import { GameIdContext } from '../../App'; -import { InputModeContext } from '../Level'; -import { CommandLine } from './CommandLine'; -import Markdown from '../Markdown'; + +import { GameIdContext } from './context'; +import { useAppDispatch, useAppSelector } from '../../state/hooks'; import { LevelInfo } from '../../state/api'; +import { levelCompleted, selectCompleted } from '../../state/progress'; +import Markdown from '../markdown'; + +import { Infos } from './infos'; +import { AllMessages, WithLspDiagnosticsContext } from './messages'; +import { Goal } from './goals'; +import { InputModeContext, ProofStateContext } from './context'; +import { CommandLine } from './command_line'; + // The mathematical formulation of the statement, supporting e.g. Latex // It takes three forms, depending on the precence of name and description: @@ -138,6 +140,10 @@ export function CommandLineInterface(props: {world: string, level: number, data: const ec = React.useContext(EditorContext); const gameId = React.useContext(GameIdContext) + const proofStateContext = React.useContext(ProofStateContext) + + const [selectedGoal, setSelectedGoal] = React.useState(0) + const dispatch = useAppDispatch() // Mark level as completed when server gives notification @@ -181,6 +187,8 @@ export function CommandLineInterface(props: {world: string, level: number, data: [] ); + const goalFilter = { reverse: false, showType: true, showInstance: true, showHiddenAssumption: true, showLetValue: true } + const serverVersion = useEventResult(ec.events.serverRestarted, result => new ServerVersion(result.serverInfo?.version ?? '')) const serverStoppedResult = useEventResult(ec.events.serverStopped); @@ -199,6 +207,19 @@ export function CommandLineInterface(props: {world: string, level: number, data:
+
+
+ {proofStateContext.proofState.goals?.goals.map((goal, i) => +
{ setSelectedGoal(i) }}> + {i ? `Goal ${i+1}` : "Active Goal"} +
)} +
+
+ {proofStateContext.proofState.goals?.goals?.length && + + } +
diff --git a/client/src/components/infoview/messages.tsx b/client/src/components/infoview/messages.tsx index 60a0229..46550f7 100644 --- a/client/src/components/infoview/messages.tsx +++ b/client/src/components/infoview/messages.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import fastIsEqual from 'react-fast-compare'; -import { Location, DocumentUri, Diagnostic, DiagnosticSeverity, PublishDiagnosticsParams } from 'vscode-languageserver-protocol'; - -import { LeanDiagnostic, RpcErrorCode } from '@leanprover/infoview-api'; - -import { basename, escapeHtml, usePausableState, useEvent, addUniqueKeys, DocumentPosition, useServerNotificationState, useEventResult } from '../../../../node_modules/lean4-infoview/src/infoview/util'; -import { ConfigContext, EditorContext, LspDiagnosticsContext, VersionContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts'; -import { Details } from '../../../../node_modules/lean4-infoview/src/infoview/collapsing'; -import { InteractiveMessage } from '../../../../node_modules/lean4-infoview/src/infoview/traceExplorer'; -import { getInteractiveDiagnostics, InteractiveDiagnostic, TaggedText_stripTags } from '@leanprover/infoview-api'; -import { RpcContext, useRpcSessionAtPos } from '../../../../node_modules/lean4-infoview/src/infoview/rpcSessions'; -import { InputModeContext } from '../Level'; +import * as React from 'react' +import fastIsEqual from 'react-fast-compare' +import { Location, DocumentUri, Diagnostic, DiagnosticSeverity, PublishDiagnosticsParams } from 'vscode-languageserver-protocol' + +import { LeanDiagnostic, RpcErrorCode, getInteractiveDiagnostics, InteractiveDiagnostic, TaggedText_stripTags } from '@leanprover/infoview-api' + +import { basename, escapeHtml, usePausableState, useEvent, addUniqueKeys, DocumentPosition, useServerNotificationState, useEventResult } from '../../../../node_modules/lean4-infoview/src/infoview/util' +import { ConfigContext, EditorContext, LspDiagnosticsContext, VersionContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts' +import { Details } from '../../../../node_modules/lean4-infoview/src/infoview/collapsing' +import { InteractiveMessage } from '../../../../node_modules/lean4-infoview/src/infoview/traceExplorer' +import { RpcContext, useRpcSessionAtPos } from '../../../../node_modules/lean4-infoview/src/infoview/rpcSessions' + +import { InputModeContext } from './context' interface MessageViewProps { uri: DocumentUri; diff --git a/client/src/components/infoview/rpcApi.ts b/client/src/components/infoview/rpc_api.ts similarity index 88% rename from client/src/components/infoview/rpcApi.ts rename to client/src/components/infoview/rpc_api.ts index 8cfc91e..3833c61 100644 --- a/client/src/components/infoview/rpcApi.ts +++ b/client/src/components/infoview/rpc_api.ts @@ -1,5 +1,8 @@ -/* This file is based on `vscode-lean4/vscode-lean4/src/rpcApi.ts ` */ - +/** + * @fileOverview Defines the interface for the communication with the server. + * + * This file is based on `vscode-lean4/vscode-lean4/src/rpcApi.ts` + */ import { ContextInfo, FVarId, CodeWithInfos, MVarId } from '@leanprover/infoview-api'; export interface GameHint { diff --git a/client/src/components/Inventory.tsx b/client/src/components/inventory.tsx similarity index 97% rename from client/src/components/Inventory.tsx rename to client/src/components/inventory.tsx index 02d660f..f713f64 100644 --- a/client/src/components/Inventory.tsx +++ b/client/src/components/inventory.tsx @@ -3,9 +3,9 @@ import { useState, useEffect } from 'react'; import './inventory.css' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faLock, faLockOpen, faBook, faHammer, faBan } from '@fortawesome/free-solid-svg-icons' -import Markdown from './Markdown'; +import { GameIdContext } from './infoview/context'; +import Markdown from './markdown'; import { useLoadDocQuery, InventoryTile, LevelInfo } from '../state/api'; -import { GameIdContext } from '../App'; export function Inventory({levelInfo, openDoc } : { diff --git a/client/src/components/LandingPage.css b/client/src/components/landing_page.css similarity index 100% rename from client/src/components/LandingPage.css rename to client/src/components/landing_page.css diff --git a/client/src/components/LandingPage.tsx b/client/src/components/landing_page.tsx similarity index 96% rename from client/src/components/LandingPage.tsx rename to client/src/components/landing_page.tsx index 7cdf947..e1727bf 100644 --- a/client/src/components/LandingPage.tsx +++ b/client/src/components/landing_page.tsx @@ -1,19 +1,18 @@ import * as React from 'react'; -import { useNavigate } from "react-router-dom"; -import { Link } from 'react-router-dom'; -import Markdown from './Markdown'; +import { useNavigate, Link } from "react-router-dom"; import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; import '@fontsource/roboto/500.css'; import '@fontsource/roboto/700.css'; -import './LandingPage.css' -import {PrivacyPolicyPopup} from './PrivacyPolicy' - +import './landing_page.css' import coverRobo from '../assets/covers/formaloversum.png' import bgImage from '../assets/bg.jpg' +import Markdown from './markdown'; +import {PrivacyPolicyPopup} from './privacy_policy' + const flag = { 'Dutch': '🇳🇱', 'English': '🇬🇧', diff --git a/client/src/components/Level.tsx b/client/src/components/level.tsx similarity index 90% rename from client/src/components/Level.tsx rename to client/src/components/level.tsx index ee37bca..19afc8f 100644 --- a/client/src/components/Level.tsx +++ b/client/src/components/level.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; import { useEffect, useState, useRef } from 'react'; +import Split from 'react-split' +import { Alert } from '@mui/material'; import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; import '@fontsource/roboto/500.css'; @@ -26,74 +28,19 @@ import type { Location } from 'vscode-languageserver-protocol'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faHome, faArrowRight, faArrowLeft, faRotateLeft } from '@fortawesome/free-solid-svg-icons' import { styled, useTheme, Theme, CSSObject } from '@mui/material/styles'; -import Split from 'react-split' -import { Alert } from '@mui/material'; +import { DocumentPosition } from '../../../node_modules/lean4-infoview/src/infoview/util'; -import { Button } from './Button' -import {Inventory, Documentation} from './Inventory'; -import Markdown from './Markdown'; -import { EditorInterface, CommandLineInterface } from './infoview/main' -import { Hints } from './infoview/hints'; -import { GameHint, InteractiveGoals } from './infoview/rpcApi'; -import { GameIdContext } from '../App'; -import { ConnectionContext, useLeanClient } from '../connection'; -import { useAppDispatch, useAppSelector } from '../hooks'; +import { GameIdContext } from './infoview/context'; +import { ConnectionContext, useLeanClient } from '../state/connection'; +import { useAppDispatch, useAppSelector } from '../state/hooks'; +import { Button } from './button' +import Markdown from './markdown'; +import {Inventory, Documentation} from './inventory'; import { useGetGameInfoQuery, useLoadLevelQuery } from '../state/api'; import { changedSelection, codeEdited, selectCode, selectSelections, progressSlice, selectCompleted } from '../state/progress'; -import { DocumentPosition } from '../../../node_modules/lean4-infoview/src/infoview/util'; -import { getInteractiveTermGoal, InteractiveDiagnostic, - UserWidgetInstance, Widget_getWidgets, RpcSessionAtPos, isRpcError, - RpcErrorCode, getInteractiveDiagnostics, InteractiveTermGoal } from '@leanprover/infoview-api'; - -export const MonacoEditorContext = React.createContext(null as any); - -export const HintContext = React.createContext<{ - showHiddenHints : boolean, - setShowHiddenHints: React.Dispatch> -}>({ - showHiddenHints: true, - setShowHiddenHints: () => {}, -}); - -export type InfoStatus = 'updating' | 'error' | 'ready'; - -export interface ProofStateProps { - // pos: DocumentPosition; - status: InfoStatus; - messages: InteractiveDiagnostic[]; - goals?: InteractiveGoals; - termGoal?: InteractiveTermGoal; - error?: string; - // userWidgets: UserWidgetInstance[]; - // rpcSess: RpcSessionAtPos; - // triggerUpdate: () => Promise; -} - -export const ProofStateContext = React.createContext<{ - proofState : ProofStateProps, - setProofState: React.Dispatch> -}>({ - proofState : { - status: 'updating', - messages: [], - goals: undefined, - termGoal: undefined, - error: undefined}, - setProofState: () => {}, -}); - - -export const InputModeContext = React.createContext<{ - commandLineMode: boolean, - setCommandLineMode: React.Dispatch>, - commandLineInput: string, - setCommandLineInput: React.Dispatch> -}>({ - commandLineMode: true, - setCommandLineMode: () => {}, - commandLineInput: "", - setCommandLineInput: () => {}, -}); +import { EditorInterface, CommandLineInterface } from './infoview/main' +import { Hints } from './hints'; +import { HintContext, InputModeContext, MonacoEditorContext, ProofContext, ProofStateContext, ProofStateProps, ProofStep } from './infoview/context'; function Level() { @@ -124,6 +71,8 @@ function PlayableLevel({worldId, levelId}) { const [showHiddenHints, setShowHiddenHints] = useState(false) + const [proof, setProof] = useState>([]) + const [proofState, setProofState] = React.useState({ status: 'updating', messages: [], @@ -238,6 +187,7 @@ function PlayableLevel({worldId, levelId}) {
+ @@ -307,6 +257,7 @@ function PlayableLevel({worldId, levelId}) { + diff --git a/client/src/components/Markdown.tsx b/client/src/components/markdown.tsx similarity index 100% rename from client/src/components/Markdown.tsx rename to client/src/components/markdown.tsx diff --git a/client/src/components/Message.tsx b/client/src/components/message.tsx similarity index 95% rename from client/src/components/Message.tsx rename to client/src/components/message.tsx index 1a745a5..3883eb0 100644 --- a/client/src/components/Message.tsx +++ b/client/src/components/message.tsx @@ -5,7 +5,7 @@ import '@fontsource/roboto/500.css'; import '@fontsource/roboto/700.css'; import { Button, Dialog, DialogContent, DialogContentText, DialogActions } from '@mui/material'; -import Markdown from './Markdown'; +import Markdown from './markdown'; function Message({ isOpen, content, close }) { diff --git a/client/src/components/PrivacyPolicy.tsx b/client/src/components/privacy_policy.tsx similarity index 100% rename from client/src/components/PrivacyPolicy.tsx rename to client/src/components/privacy_policy.tsx diff --git a/client/src/components/Welcome.tsx b/client/src/components/welcome.tsx similarity index 93% rename from client/src/components/Welcome.tsx rename to client/src/components/welcome.tsx index 0382b6b..a69771a 100644 --- a/client/src/components/Welcome.tsx +++ b/client/src/components/welcome.tsx @@ -1,28 +1,21 @@ import * as React from 'react'; import { useState, useEffect, useRef } from 'react'; -import './welcome.css' -import cytoscape, { LayoutOptions } from 'cytoscape' -import klay from 'cytoscape-klay'; +import { Link } from 'react-router-dom'; import { useNavigate } from 'react-router-dom'; import { useSelector } from 'react-redux'; import Split from 'react-split' - -import GameMenu from './GameMenu'; -import {PrivacyPolicy} from './PrivacyPolicy'; - -cytoscape.use( klay ); - import { Box, Typography, CircularProgress } from '@mui/material'; -import { useGetGameInfoQuery } from '../state/api'; -import { Link } from 'react-router-dom'; -import Markdown from './Markdown'; +import cytoscape, { LayoutOptions } from 'cytoscape' +import klay from 'cytoscape-klay'; +import './welcome.css' +import { GameIdContext } from './infoview/context'; import { selectCompleted } from '../state/progress'; -import { GameIdContext } from '../App'; -import { Button } from './Button'; - -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faDownload, faUpload, faEraser } from '@fortawesome/free-solid-svg-icons' +import { useGetGameInfoQuery } from '../state/api'; +import Markdown from './markdown'; +import GameMenu from './game_menu'; +import {PrivacyPolicy} from './privacy_policy'; +cytoscape.use( klay ); const N = 24 // max number of levels per world const R = 800 // radius of a world diff --git a/client/src/index.tsx b/client/src/index.tsx index 814407f..4146aaf 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { createRoot } from 'react-dom/client'; -import App from './App'; -import { ConnectionContext, connection } from './connection' +import App from './app'; +import { ConnectionContext, connection } from './state/connection' import { store } from './state/store'; import { Provider } from 'react-redux'; import { @@ -9,10 +9,10 @@ import { RouterProvider, Route, } from "react-router-dom"; -import ErrorPage from './ErrorPage'; -import Welcome from './components/Welcome'; -import LandingPage from './components/LandingPage'; -import Level from './components/Level'; +import ErrorPage from './components/error_page'; +import Welcome from './components/welcome'; +import LandingPage from './components/landing_page'; +import Level from './components/level'; import { monacoSetup } from 'lean4web/client/src/monacoSetup'; import { redirect } from 'react-router-dom'; diff --git a/client/src/state/api.ts b/client/src/state/api.ts index 349b905..19c4c5e 100644 --- a/client/src/state/api.ts +++ b/client/src/state/api.ts @@ -1,5 +1,5 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { Connection } from '../connection' +import { Connection } from './connection' interface GameInfo { title: null|string, diff --git a/client/src/connection.ts b/client/src/state/connection.ts similarity index 94% rename from client/src/connection.ts rename to client/src/state/connection.ts index 2d630ac..3a132a8 100644 --- a/client/src/connection.ts +++ b/client/src/state/connection.ts @@ -1,9 +1,10 @@ +/** + * @fileOverview todo + */ +import * as React from 'react'; import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js' import { LeanClient } from 'lean4web/client/src/editor/leanclient'; -import * as React from 'react'; -import { useState } from 'react'; - export class Connection { private game: string = undefined // We only keep a connection to a single game at a time @@ -54,7 +55,7 @@ export const ConnectionContext = React.createContext(null); export const useLeanClient = (gameId) => { const leanClient = connection.getLeanClient(gameId) - const [leanClientStarted, setLeanClientStarted] = useState(leanClient.isStarted()) + const [leanClientStarted, setLeanClientStarted] = React.useState(leanClient.isStarted()) React.useEffect(() => { const t1 = leanClient.restarted(() => { console.log("START"); setLeanClientStarted(true) }) diff --git a/client/src/hooks.ts b/client/src/state/hooks.ts similarity index 82% rename from client/src/hooks.ts rename to client/src/state/hooks.ts index afdce0a..60a4163 100644 --- a/client/src/hooks.ts +++ b/client/src/state/hooks.ts @@ -1,5 +1,5 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' -import type { RootState, AppDispatch } from './state/store' +import type { RootState, AppDispatch } from './store' // Use throughout your app instead of plain `useDispatch` and `useSelector` export const useAppDispatch: () => AppDispatch = useDispatch diff --git a/client/src/state/localStorage.ts b/client/src/state/local_storage.ts similarity index 100% rename from client/src/state/localStorage.ts rename to client/src/state/local_storage.ts diff --git a/client/src/state/progress.ts b/client/src/state/progress.ts index 72816ff..cf1a656 100644 --- a/client/src/state/progress.ts +++ b/client/src/state/progress.ts @@ -1,6 +1,6 @@ import { createSlice } from '@reduxjs/toolkit' import type { PayloadAction } from '@reduxjs/toolkit' -import { loadState } from "./localStorage"; +import { loadState } from "./local_storage"; export interface GameProgressState { [world: string] : {[level: number]: LevelProgressState} diff --git a/client/src/state/store.ts b/client/src/state/store.ts index d0c28a6..f6bfd4c 100644 --- a/client/src/state/store.ts +++ b/client/src/state/store.ts @@ -1,10 +1,11 @@ import { configureStore } from '@reduxjs/toolkit'; -import { connection } from '../connection' -import thunkMiddleware from 'redux-thunk' +import { debounce } from "debounce"; + +import { connection } from './connection' import { apiSlice } from './api' import { progressSlice } from './progress' -import { saveState } from "./localStorage"; -import { debounce } from "debounce"; +import { saveState } from "./local_storage"; + export const store = configureStore({ reducer: { diff --git a/package-lock.json b/package-lock.json index 3b70d6c..8ae9f0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@emotion/styled": "^11.10.5", "@fontsource/roboto": "^4.5.8", "@fontsource/roboto-mono": "^4.5.8", + "@leanprover/infoview": "^0.4.3", "@mui/icons-material": "^5.11.0", "@mui/material": "^5.11.1", "@reduxjs/toolkit": "^1.9.1", @@ -2095,9 +2096,9 @@ } }, "node_modules/@leanprover/infoview": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@leanprover/infoview/-/infoview-0.4.2.tgz", - "integrity": "sha512-Bj+q/7n1xlnpRd4xsJ75uikZPwW5id/G4G1JPqhbbfMacTwAgzLNFaqJhzBrIUuF5nxJYGKRqRIeFtkalGxJ0g==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@leanprover/infoview/-/infoview-0.4.3.tgz", + "integrity": "sha512-SufdOr2myHAbZNUmobfQdAhsEC5H9ddi3KS0z1v/8riWSMm+yJk3u4LxVuzCmmSmV2QxFqtFzn5z+HQqj1Vo7g==", "dependencies": { "@leanprover/infoview-api": "~0.2.1", "@vscode/codicons": "^0.0.32", diff --git a/package.json b/package.json index 89f53cc..4636050 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@emotion/styled": "^11.10.5", "@fontsource/roboto": "^4.5.8", "@fontsource/roboto-mono": "^4.5.8", + "@leanprover/infoview": "^0.4.3", "@mui/icons-material": "^5.11.0", "@mui/material": "^5.11.1", "@reduxjs/toolkit": "^1.9.1",