scroll to selected step

pull/118/head
Jon Eugster 3 years ago
parent 0a2c4552bf
commit 446a33e5e8

@ -2,25 +2,25 @@ import { GameHint } from "./infoview/rpc_api";
import * as React from 'react'; import * as React from 'react';
import Markdown from './markdown'; import Markdown from './markdown';
export function Hint({hint, selected, toggleSelection} : {hint: GameHint, selected: boolean, toggleSelection: any}) { export function Hint({hint, step, selected, toggleSelection} : {hint: GameHint, step: number, selected: number, toggleSelection: any}) {
return <div className={"message information" + (selected ? ' selected' : '')} onClick={toggleSelection}> return <div className={`message information step-${step}` + (step == selected ? ' selected' : '')} onClick={toggleSelection}>
<Markdown>{hint.text}</Markdown> <Markdown>{hint.text}</Markdown>
</div> </div>
} }
export function AdditionalHint({hint, selected, toggleSelection} : {hint: GameHint, selected: boolean, toggleSelection: any}) { export function AdditionalHint({hint, step, selected, toggleSelection} : {hint: GameHint, step: number, selected: number, toggleSelection: any}) {
return <div className={"message warning" + (selected ? ' selected' : '')} onClick={toggleSelection}> return <div className={`message warning step-${step}` + (step == selected ? ' selected' : '')} onClick={toggleSelection}>
<Markdown>{hint.text}</Markdown> <Markdown>{hint.text}</Markdown>
</div> </div>
} }
export function Hints({hints, showHidden, selected, toggleSelection} : {hints: GameHint[], showHidden: boolean, selected: boolean, toggleSelection: any}) { export function Hints({hints, showHidden, step, selected, toggleSelection} : {hints: GameHint[], showHidden: boolean, step: number, selected: number, toggleSelection: any}) {
const openHints = hints.filter(hint => !hint.hidden) const openHints = hints.filter(hint => !hint.hidden)
const hiddenHints = hints.filter(hint => hint.hidden) const hiddenHints = hints.filter(hint => hint.hidden)
return <> return <>
{openHints.map(hint => <Hint hint={hint} selected={selected} toggleSelection={toggleSelection}/>)} {openHints.map(hint => <Hint hint={hint} step={step} selected={selected} toggleSelection={toggleSelection}/>)}
{showHidden && hiddenHints.map(hint => <AdditionalHint hint={hint} selected={selected} toggleSelection={toggleSelection}/>)} {showHidden && hiddenHints.map(hint => <AdditionalHint hint={hint} step={step} selected={selected} toggleSelection={toggleSelection}/>)}
</> </>
} }

@ -235,7 +235,7 @@ export const OtherGoals = React.memo((props: GoalProps2) => {
</> </>
}) })
// TODO: deprecated
export const ProofDisplay = React.memo((props : ProofDisplayProps) => { export const ProofDisplay = React.memo((props : ProofDisplayProps) => {
const { proof } = props const { proof } = props
const steps = proof.match(/.+/g) const steps = proof.match(/.+/g)

@ -124,7 +124,6 @@ const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => {
<div className="goals-section"> <div className="goals-section">
{ goals && goals.goals.length > 0 && <> { goals && goals.goals.length > 0 && <>
<MainAssumptions filter={goalFilter} key='mainGoal' goals={goals.goals} /> <MainAssumptions filter={goalFilter} key='mainGoal' goals={goals.goals} />
<ProofDisplay proof={proof}/>
<OtherGoals filter={goalFilter} goals={goals.goals} /> <OtherGoals filter={goalFilter} goals={goals.goals} />
</>} </>}
</div> </div>

@ -314,7 +314,7 @@ export function CommandLineInterface(props: {world: string, level: number, data:
} }
} }
function selectStep(line: number) { function toggleSelectStep(line: number) {
return (ev) => { return (ev) => {
if (selectedStep == line) { if (selectedStep == line) {
setSelectedStep(undefined) setSelectedStep(undefined)
@ -326,6 +326,16 @@ export function CommandLineInterface(props: {world: string, level: number, data:
} }
} }
// Scroll to element if selection changes
React.useEffect(() => {
if (selectedStep) {
Array.from(proofPanelRef.current?.getElementsByClassName(`step-${selectedStep}`)).map((elem) => {
elem.scrollIntoView({block: "center"})
})
}
}, [selectedStep])
const completed = useAppSelector(selectCompleted(gameId, props.world, props.level)) const completed = useAppSelector(selectCompleted(gameId, props.world, props.level))
/* Set up updates to the global infoview seither you solved the level with warnings or your last command contains a syntax error Lean can't parseate on editor events. */ /* Set up updates to the global infoview seither you solved the level with warnings or your last command contains a syntax error Lean can't parseate on editor events. */
@ -378,7 +388,7 @@ export function CommandLineInterface(props: {world: string, level: number, data:
</div> </div>
} else { } else {
return <> return <>
<div className={'step' + (selectedStep == i ? ' selected' : '')} onClick={selectStep(i)}> <div className={`step step-${i}` + (selectedStep == i ? ' selected' : '')} onClick={toggleSelectStep(i)}>
<Command command={step.command} deleteProof={deleteProof(i)}/> <Command command={step.command} deleteProof={deleteProof(i)}/>
<Errors errors={step.errors} commandLineMode={true}/> <Errors errors={step.errors} commandLineMode={true}/>
<GoalsTab proofStep={step}/> <GoalsTab proofStep={step}/>

@ -40,6 +40,7 @@ import { changedSelection, codeEdited, selectCode, selectSelections, progressSli
import { DualEditor } from './infoview/main' import { DualEditor } from './infoview/main'
import { Hints } from './hints'; import { Hints } from './hints';
import { InputModeContext, MonacoEditorContext, ProofContext, ProofStep, SelectionContext } from './infoview/context'; import { InputModeContext, MonacoEditorContext, ProofContext, ProofStep, SelectionContext } from './infoview/context';
import { hasInteractiveErrors } from './infoview/command_line';
function Level() { function Level() {
@ -106,6 +107,15 @@ function PlayableLevel({worldId, levelId}) {
} }
}, [commandLineMode]) }, [commandLineMode])
// Scroll to element if selection changes
React.useEffect(() => {
if (selectedStep) {
Array.from(chatRef.current?.getElementsByClassName(`step-${selectedStep}`)).map((elem) => {
elem.scrollIntoView({block: "center"})
})
}
}, [selectedStep])
/** 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
* `CommandLineInterface`. * `CommandLineInterface`.
*/ */
@ -217,7 +227,12 @@ function PlayableLevel({worldId, levelId}) {
</div> </div>
} }
{proof.map((step, i) => { {proof.map((step, i) => {
return <Hints hints={step.hints} showHidden={showHiddenHints} selected={i == selectedStep} toggleSelection={toggleSelection(i)}/> // It the last step has errors, it will have the same hints
// as the second-to-last step. Therefore we should not display them.
if (!(i == proof.length - 1 && hasInteractiveErrors(step.errors))) {
return <Hints hints={step.hints} showHidden={showHiddenHints} step={i}
selected={selectedStep} toggleSelection={toggleSelection(i)}/>
}
})} })}
{completed && {completed &&
<> <>

Loading…
Cancel
Save