diff --git a/frontend/src/components/Diff/Diff.tsx b/frontend/src/components/Diff/Diff.tsx index b2108402..d03bcf96 100644 --- a/frontend/src/components/Diff/Diff.tsx +++ b/frontend/src/components/Diff/Diff.tsx @@ -1,8 +1,9 @@ /* eslint css-modules/no-unused-class: off */ -import { createContext, CSSProperties, forwardRef, HTMLAttributes, useRef, useState } from "react" +import { createContext, CSSProperties, forwardRef, HTMLAttributes, MutableRefObject, useRef, useState } from "react" import { VersionsIcon } from "@primer/octicons-react" +import { EditorView } from "codemirror" import { DiffResult } from "objdiff-wasm" import AutoSizer from "react-virtualized-auto-sizer" import { FixedSizeList } from "react-window" @@ -94,6 +95,21 @@ function ThreeWayToggleButton({ enabled, setEnabled }: { enabled: boolean, setEn } +export function scrollToLineNumber(editorView: MutableRefObject, lineNumber: number) { + if (!editorView) { + return + } + if (lineNumber <= editorView.current.state.doc.lines) { + // check if the source line <= number of lines + // which can be false if pragmas are used to force line numbers + const line = editorView.current.state.doc.line(lineNumber) + if (line) { + const { top } = editorView.current.lineBlockAt(line.to) + editorView.current.scrollDOM.scrollTo({ top, behavior: "smooth" }) + } + } +} + export const PADDING_TOP = 8 export const PADDING_BOTTOM = 8 diff --git a/frontend/src/components/Diff/DiffRowAsmDiffer.tsx b/frontend/src/components/Diff/DiffRowAsmDiffer.tsx index cc2d281d..45aa3799 100644 --- a/frontend/src/components/Diff/DiffRowAsmDiffer.tsx +++ b/frontend/src/components/Diff/DiffRowAsmDiffer.tsx @@ -1,14 +1,17 @@ /* eslint css-modules/no-unused-class: off */ -import { CSSProperties, memo, useContext } from "react" +import { CSSProperties, MutableRefObject, memo, useContext } from "react" import classNames from "classnames" +import { EditorView } from "codemirror" import memoize from "memoize-one" import { areEqual } from "react-window" import * as api from "@/lib/api" -import { PADDING_TOP, SelectedSourceLineContext } from "./Diff" +import { ScrollContext } from "../ScrollContext" + +import { PADDING_TOP, SelectedSourceLineContext, scrollToLineNumber } from "./Diff" import styles from "./Diff.module.scss" import { Highlighter } from "./Highlighter" @@ -61,6 +64,7 @@ function DiffCell({ cell, className, highlighter }: { highlighter: Highlighter }) { const selectedSourceLine = useContext(SelectedSourceLineContext) + const sourceEditor = useContext>(ScrollContext) const hasLineNo = typeof cell?.src_line != "undefined" if (!cell) @@ -71,7 +75,7 @@ function DiffCell({ cell, className, highlighter }: { [styles.highlight]: hasLineNo && cell.src_line == selectedSourceLine, })} > - {hasLineNo && {cell.src_line}} + {hasLineNo && } } diff --git a/frontend/src/components/Diff/DiffRowObjdiff.tsx b/frontend/src/components/Diff/DiffRowObjdiff.tsx index 567ae372..a0a9fffa 100644 --- a/frontend/src/components/Diff/DiffRowObjdiff.tsx +++ b/frontend/src/components/Diff/DiffRowObjdiff.tsx @@ -1,13 +1,16 @@ /* eslint css-modules/no-unused-class: off */ -import { CSSProperties, memo, useContext } from "react" +import { CSSProperties, MutableRefObject, memo, useContext } from "react" import classNames from "classnames" +import { EditorView } from "codemirror" import memoize from "memoize-one" import { DiffKind, DiffResult, FunctionDiff, InstructionDiff, ObjectDiff, displayDiff, oneof } from "objdiff-wasm" import { areEqual } from "react-window" -import { PADDING_TOP, SelectedSourceLineContext } from "./Diff" +import { ScrollContext } from "../ScrollContext" + +import { PADDING_TOP, SelectedSourceLineContext, scrollToLineNumber } from "./Diff" import styles from "./Diff.module.scss" import { Highlighter } from "./Highlighter" @@ -123,6 +126,7 @@ function DiffCell({ cell, baseAddress, className, highlighter }: { highlighter?: Highlighter }) { const selectedSourceLine = useContext(SelectedSourceLineContext) + const sourceEditor = useContext>(ScrollContext) const hasLineNo = typeof cell?.instruction?.line_number != "undefined" if (!cell) @@ -149,7 +153,7 @@ function DiffCell({ cell, baseAddress, className, highlighter }: { [styles.highlight]: hasLineNo && cell.instruction.line_number == selectedSourceLine, })} > - {hasLineNo && {cell.instruction.line_number}} + {hasLineNo && } } diff --git a/frontend/src/components/Scratch/Scratch.tsx b/frontend/src/components/Scratch/Scratch.tsx index b2c2c8e2..1256581d 100644 --- a/frontend/src/components/Scratch/Scratch.tsx +++ b/frontend/src/components/Scratch/Scratch.tsx @@ -16,6 +16,7 @@ import CompilationPanel from "../Diff/CompilationPanel" import CodeMirror from "../Editor/CodeMirror" import ErrorBoundary from "../ErrorBoundary" import ScoreBadge, { calculateScorePercent } from "../ScoreBadge" +import { ScrollContext } from "../ScrollContext" import { Tab, TabCloseButton } from "../Tabs" import useLanguageServer from "./hooks/useLanguageServer" @@ -338,11 +339,13 @@ export default function Scratch({ {matchProgressBarEnabledSetting &&
} - {layout && } + {layout && + + } {offlineOverlay} diff --git a/frontend/src/components/ScrollContext.tsx b/frontend/src/components/ScrollContext.tsx new file mode 100644 index 00000000..4ffbc65f --- /dev/null +++ b/frontend/src/components/ScrollContext.tsx @@ -0,0 +1,3 @@ +import { createContext } from "react" + +export const ScrollContext = createContext(null)