From 88fa756ab96ccfc882e3f689ba9f62e221225b9f Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Sat, 22 Feb 2025 11:03:16 +0100 Subject: [PATCH] Handle scrollable editors in the ActionsGutter --- .../conflicts-resolution/actions-gutter.tsx | 18 ++++++++++++++---- src/views/conflicts-resolution/component.tsx | 10 ++++++++++ src/views/conflicts-resolution/editor-pane.tsx | 16 ++++++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/views/conflicts-resolution/actions-gutter.tsx b/src/views/conflicts-resolution/actions-gutter.tsx index 1abe582..97364e5 100644 --- a/src/views/conflicts-resolution/actions-gutter.tsx +++ b/src/views/conflicts-resolution/actions-gutter.tsx @@ -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 = ({ diffChunks, lineHeight, + leftEditorTopOffset: leftEditorTopLineOffset, + rightEditorTopLineOffset: rightEditorTopOffset, onAcceptLeft, onAcceptRight, onReject, @@ -39,10 +44,15 @@ const ActionsGutter: React.FC = ({ }, []); 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)" diff --git a/src/views/conflicts-resolution/component.tsx b/src/views/conflicts-resolution/component.tsx index 91281f2..fca0198 100644 --- a/src/views/conflicts-resolution/component.tsx +++ b/src/views/conflicts-resolution/component.tsx @@ -42,6 +42,12 @@ const DiffView: React.FC = ({ const handleEditorReady = (editor: EditorView) => { setLineHeight(editor.defaultLineHeight); }; + + const [leftEditorTopOffset, setLeftEditorTopOffset] = + React.useState(0); + const [rightEditorTopOffset, setRightEditorTopOffset] = + React.useState(0); + const diffs = diff(oldText, newText); return ( @@ -62,12 +68,15 @@ const DiffView: React.FC = ({ }} onEditorUpdate={handleEditorReady} onContentChange={onOldTextChange} + onScrollTopUpdate={setLeftEditorTopOffset} />
{ if (chunk.type === "add") { const oldLines = oldText.split("\n"); @@ -141,6 +150,7 @@ const DiffView: React.FC = ({ isOriginal: false, }} onContentChange={onNewTextChange} + onScrollTopUpdate={setRightEditorTopOffset} />
diff --git a/src/views/conflicts-resolution/editor-pane.tsx b/src/views/conflicts-resolution/editor-pane.tsx index 86c3de0..4367466 100644 --- a/src/views/conflicts-resolution/editor-pane.tsx +++ b/src/views/conflicts-resolution/editor-pane.tsx @@ -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 = (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 = (props) => { }, }), markdown(), + EditorView.domEventObservers({ + scroll(event) { + onScrollTopUpdate?.(event.target.scrollTop); + }, + }), ]; }, [highlightPluginSpec]);