Handle scrollable editors in the ActionsGutter

This commit is contained in:
Silvano Cerza 2025-02-22 11:03:16 +01:00
parent 64d0223aa0
commit 88fa756ab9
3 changed files with 38 additions and 6 deletions

View file

@ -11,6 +11,9 @@ interface ActionsGutterProps {
// This is essential to correctly draw the lines between
// the left and right editor
lineHeight: number;
// These two properties are necessary to handle editors scrolling
leftEditorTopOffset: number;
rightEditorTopLineOffset: number;
onAcceptLeft: (chunk: DiffChunk) => void;
onAcceptRight: (chunk: DiffChunk) => void;
onReject: (chunk: DiffChunk) => void;
@ -19,6 +22,8 @@ interface ActionsGutterProps {
const ActionsGutter: React.FC<ActionsGutterProps> = ({
diffChunks,
lineHeight,
leftEditorTopOffset: leftEditorTopLineOffset,
rightEditorTopLineOffset: rightEditorTopOffset,
onAcceptLeft,
onAcceptRight,
onReject,
@ -39,10 +44,15 @@ const ActionsGutter: React.FC<ActionsGutterProps> = ({
}, []);
const drawChunk = (chunk: DiffChunk, index: number) => {
const topLeft = (chunk.startLeftLine - 1) * lineHeight;
const bottomLeft = (chunk.endLeftLine - 1) * lineHeight;
const topRight = (chunk.startRightLine - 1) * lineHeight;
const bottomRight = (chunk.endRightLine - 1) * lineHeight;
// The offsets are substracted to compensate the editors scrolling
const topLeft =
(chunk.startLeftLine - 1) * lineHeight - leftEditorTopLineOffset;
const bottomLeft =
(chunk.endLeftLine - 1) * lineHeight - leftEditorTopLineOffset;
const topRight =
(chunk.startRightLine - 1) * lineHeight - rightEditorTopOffset;
const bottomRight =
(chunk.endRightLine - 1) * lineHeight - rightEditorTopOffset;
const color =
chunk.type == "add"
? "var(--color-green)"

View file

@ -42,6 +42,12 @@ const DiffView: React.FC<DiffViewProps> = ({
const handleEditorReady = (editor: EditorView) => {
setLineHeight(editor.defaultLineHeight);
};
const [leftEditorTopOffset, setLeftEditorTopOffset] =
React.useState<number>(0);
const [rightEditorTopOffset, setRightEditorTopOffset] =
React.useState<number>(0);
const diffs = diff(oldText, newText);
return (
@ -62,12 +68,15 @@ const DiffView: React.FC<DiffViewProps> = ({
}}
onEditorUpdate={handleEditorReady}
onContentChange={onOldTextChange}
onScrollTopUpdate={setLeftEditorTopOffset}
/>
</div>
<div style={{ minWidth: "160px", width: "auto" }}>
<ActionsGutter
diffChunks={diffs}
lineHeight={lineHeight}
leftEditorTopOffset={leftEditorTopOffset}
rightEditorTopLineOffset={rightEditorTopOffset}
onAcceptLeft={(chunk: DiffChunk) => {
if (chunk.type === "add") {
const oldLines = oldText.split("\n");
@ -141,6 +150,7 @@ const DiffView: React.FC<DiffViewProps> = ({
isOriginal: false,
}}
onContentChange={onNewTextChange}
onScrollTopUpdate={setRightEditorTopOffset}
/>
</div>
</div>

View file

@ -12,11 +12,18 @@ interface EditorPaneProps {
highlightPluginSpec: DiffHighlightPluginSpec;
onEditorUpdate?: (editor: EditorView) => void;
onContentChange: (content: string) => void;
// Used to track the offset of the first line when the editor scrolls
onScrollTopUpdate?: (topOffset: number) => void;
}
const EditorPane: React.FC<EditorPaneProps> = (props) => {
const { content, highlightPluginSpec, onEditorUpdate, onContentChange } =
props;
const {
content,
highlightPluginSpec,
onEditorUpdate,
onContentChange,
onScrollTopUpdate,
} = props;
const extensions = React.useMemo(() => {
return [
// basicSetup minus line numbers
@ -45,6 +52,11 @@ const EditorPane: React.FC<EditorPaneProps> = (props) => {
},
}),
markdown(),
EditorView.domEventObservers({
scroll(event) {
onScrollTopUpdate?.(event.target.scrollTop);
},
}),
];
}, [highlightPluginSpec]);