De-lazify the code+context tabs (again) (#1540)

* De-lazify the code+context tabs (again)

* track compiler opts scroll position

* cleanup
This commit is contained in:
Mark Street
2025-05-17 09:06:11 +01:00
committed by GitHub
parent ce49b2ed39
commit 29e01b535e
2 changed files with 71 additions and 27 deletions
+29 -27
View File
@@ -40,6 +40,7 @@ import ScratchToolbar from "./ScratchToolbar";
import { StreamLanguage } from "@codemirror/language";
import { pascal } from "@/lib/codemirror/pascal";
import ObjdiffPanel from "../Diff/ObjdiffPanel";
import ScrollRestorer from "../ScrollRestorer";
enum TabId {
ABOUT = "scratch_about",
@@ -164,6 +165,8 @@ export default function Scratch({
const contextEditor = useRef<EditorView>(null);
const [valueVersion, incrementValueVersion] = useReducer((x) => x + 1, 0);
const compilerOptsScrollPosition = useRef(0);
const [isModified, setIsModified] = useState(false);
const setScratch = (scratch: Partial<api.Scratch>) => {
onChange(scratch);
@@ -263,19 +266,17 @@ export default function Scratch({
saveContext();
}}
>
{() => (
<CodeMirror
viewRef={sourceEditor}
className={styles.editor}
value={scratch.source_code}
valueVersion={valueVersion}
onChange={(value) => {
setScratch({ source_code: value });
}}
onSelectedLineChange={setSelectedSourceLine}
extensions={cmExtensionsSource}
/>
)}
<CodeMirror
viewRef={sourceEditor}
className={styles.editor}
value={scratch.source_code}
valueVersion={valueVersion}
onChange={(value) => {
setScratch({ source_code: value });
}}
onSelectedLineChange={setSelectedSourceLine}
extensions={cmExtensionsSource}
/>
</Tab>
);
case TabId.CONTEXT:
@@ -290,18 +291,16 @@ export default function Scratch({
saveSource();
}}
>
{() => (
<CodeMirror
viewRef={contextEditor}
className={styles.editor}
value={scratch.context}
valueVersion={valueVersion}
onChange={(value) => {
setScratch({ context: value });
}}
extensions={cmExtensionsContext}
/>
)}
<CodeMirror
viewRef={contextEditor}
className={styles.editor}
value={scratch.context}
valueVersion={valueVersion}
onChange={(value) => {
setScratch({ context: value });
}}
extensions={cmExtensionsContext}
/>
</Tab>
);
case TabId.OPTIONS:
@@ -313,7 +312,10 @@ export default function Scratch({
className={styles.compilerOptsTab}
>
{() => (
<div className={styles.compilerOptsContainer}>
<ScrollRestorer
className={styles.compilerOptsContainer}
scrollPositionRef={compilerOptsScrollPosition}
>
<CompilerOpts
platform={scratch.platform}
value={scratch}
@@ -327,7 +329,7 @@ export default function Scratch({
setScratch({ match_override: m })
}
/>
</div>
</ScrollRestorer>
)}
</Tab>
);
@@ -0,0 +1,42 @@
import type React from "react";
import { useEffect, useRef } from "react";
interface ScrollRestorerProps {
scrollPositionRef: React.RefObject<number>;
children: React.ReactNode;
className?: string;
}
const ScrollRestorer: React.FC<ScrollRestorerProps> = ({
scrollPositionRef,
children,
className,
}) => {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
// Restore scroll position on initial mount
el.scrollTop = scrollPositionRef.current;
// Save scroll position on scroll
const handleScroll = () => {
scrollPositionRef.current = el.scrollTop;
};
el.addEventListener("scroll", handleScroll);
return () => {
el.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<div ref={containerRef} className={className}>
{children}
</div>
);
};
export default ScrollRestorer;