fix(app): stabilize canvas diff rendering
Keep diff headers and painted content on the same scroll clock while preserving native scrolling and independent per-file horizontal offsets. Complete review, selection, typography, tree, and palette parity without returning line rendering to React.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import type { DiffDocumentModel } from "./types";
|
||||
|
||||
export interface NativeCanvasSlab {
|
||||
key: string;
|
||||
path: string;
|
||||
fileIndex: number;
|
||||
top: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export function nativeStickyHeaderIndices(fileCount: number): number[] {
|
||||
return Array.from({ length: fileCount }, (_, index) => index * 2 + 1);
|
||||
}
|
||||
|
||||
export function buildNativeCanvasSlabs(
|
||||
model: DiffDocumentModel,
|
||||
viewportHeight: number,
|
||||
): NativeCanvasSlab[] {
|
||||
const slabHeight = Math.max(768, viewportHeight * 2);
|
||||
return model.files.flatMap((file) => {
|
||||
const slabs: NativeCanvasSlab[] = [];
|
||||
for (let top = file.bodyTop; top < file.bottom; top += slabHeight) {
|
||||
const height = Math.min(slabHeight, file.bottom - top);
|
||||
slabs.push({
|
||||
key: `${file.path}:${top}:${height}`,
|
||||
path: file.path,
|
||||
fileIndex: file.fileIndex,
|
||||
top,
|
||||
height,
|
||||
});
|
||||
}
|
||||
return slabs;
|
||||
});
|
||||
}
|
||||
|
||||
export function nativeCanvasSlabsForViewport(
|
||||
slabs: readonly NativeCanvasSlab[],
|
||||
scrollTop: number,
|
||||
viewportHeight: number,
|
||||
): NativeCanvasSlab[] {
|
||||
const top = Math.max(0, scrollTop - viewportHeight);
|
||||
const bottom = scrollTop + viewportHeight * 2;
|
||||
return slabs.filter((slab) => slab.top < bottom && slab.top + slab.height > top);
|
||||
}
|
||||
|
||||
export function nativeCanvasWindowBucket(scrollTop: number, viewportHeight: number): number {
|
||||
"worklet";
|
||||
return Math.floor(Math.max(0, scrollTop) / Math.max(1, viewportHeight / 2));
|
||||
}
|
||||
|
||||
export function nativeCanvasWindowTop(bucket: number, viewportHeight: number): number {
|
||||
"worklet";
|
||||
return bucket * Math.max(1, viewportHeight / 2);
|
||||
}
|
||||
Reference in New Issue
Block a user