This commit is contained in:
Timothy Jaeryang Baek 2026-10-14 14:41:09 +04:00
parent d49bdc5257
commit 097ecdb69b
2 changed files with 32 additions and 4 deletions

View file

@ -3,7 +3,7 @@
import { getContext } from 'svelte';
import { copyToClipboard } from '$lib/utils';
import { basicSetup, EditorView } from 'codemirror';
import { Compartment } from '@codemirror/state';
import { Compartment, type Text } from '@codemirror/state';
import { keymap, type ViewUpdate } from '@codemirror/view';
import { indentWithTab, isolateHistory } from '@codemirror/commands';
import { LanguageDescription, indentUnit } from '@codemirror/language';
@ -14,7 +14,7 @@
import ConfirmDialog from './ConfirmDialog.svelte';
import FileCodeEditor from '$lib/components/chat/FileNav/FileCodeEditor.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
import { lineAlignment, alignChangedLines } from './diffEditorAlignment';
import { lineAlignment, alignChangedLines, clearLineAlignment } from './diffEditorAlignment';
import {
copyChunk,
selectedChunk,
@ -181,6 +181,8 @@
let view: MergeView | null = null;
let observer: MutationObserver | undefined;
let alignmentFrame = 0;
let alignmentDocuments: readonly [Text, Text] | null = null;
let alignmentGeometry = '';
const themes = [new Compartment(), new Compartment()];
const language = [new Compartment(), new Compartment()];
const path = session?.path;
@ -208,7 +210,22 @@
alignmentFrame = requestAnimationFrame(() => {
alignmentFrame = 0;
if (!disposed && view) {
alignChangedLines(view.a, view.b, view.chunks);
const documents = [view.a.state.doc, view.b.state.doc] as const;
const geometry = [
view.a.contentDOM.clientWidth,
view.b.contentDOM.clientWidth,
view.a.defaultLineHeight,
view.b.defaultLineHeight
].join(':');
const reset =
alignmentDocuments &&
(alignmentDocuments[0] !== documents[0] ||
alignmentDocuments[1] !== documents[1] ||
geometry !== alignmentGeometry);
alignmentDocuments = documents;
alignmentGeometry = geometry;
if (!reset || !clearLineAlignment(view.a, view.b))
alignChangedLines(view.a, view.b, view.chunks);
view.reconfigure({});
}
});

View file

@ -30,11 +30,22 @@ export const lineAlignment = StateField.define<DecorationSet>({
create: () => Decoration.none,
update: (value, transaction) => {
for (const effect of transaction.effects) if (effect.is(setSpacers)) return effect.value;
return value.map(transaction.changes);
return transaction.docChanged ? Decoration.none : value;
},
provide: (field) => EditorView.decorations.from(field)
});
export function clearLineAlignment(a: EditorView, b: EditorView) {
let changed = false;
for (const view of [a, b]) {
if (view.state.field(lineAlignment).size) {
view.dispatch({ effects: setSpacers.of(Decoration.none) });
changed = true;
}
}
return changed;
}
// Only remeasure paired rows present in both virtualized viewports. Recomputing
// offscreen spacers from estimated heights would move already aligned content.
export function alignChangedLines(a: EditorView, b: EditorView, chunks: readonly Chunk[]) {