Make large diffs open quickly and scroll as one surface (#3212)

* perf(app): virtualize large diff rendering

Render bounded diff row groups through one vertical list and one horizontal surface. Bound retained list ranges when expansion grows the data set so large diffs paint promptly without sacrificing scrolling behavior.

* refactor(app): normalize working tree diff options

* fix(app): keep wide diff text reachable
This commit is contained in:
Mohamed Boudra
2026-08-11 12:18:48 +02:00
committed by GitHub
parent 7253228dc5
commit b599d38a77
17 changed files with 1717 additions and 717 deletions
@@ -1,12 +1,23 @@
import { useCallback } from "react";
import { ScrollView, type LayoutChangeEvent, type StyleProp, type ViewStyle } from "react-native";
import { useCallback, useId, useLayoutEffect, useState } from "react";
import {
type LayoutChangeEvent,
type NativeScrollEvent,
type NativeSyntheticEvent,
type StyleProp,
type ViewStyle,
} from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import type { SharedValue } from "react-native-reanimated";
import { useHorizontalScrollOptional } from "@/contexts/horizontal-scroll-context";
import { useFileExplorerCloseGestureRef } from "@/mobile-panels/gestures";
interface DiffScrollProps {
children: React.ReactNode;
scrollViewWidth: number;
onScrollViewWidthChange: (width: number) => void;
style?: StyleProp<ViewStyle>;
contentContainerStyle?: StyleProp<ViewStyle>;
offset: SharedValue<number>;
testID?: string;
}
export function DiffScroll({
@@ -14,9 +25,31 @@ export function DiffScroll({
onScrollViewWidthChange,
style,
contentContainerStyle,
offset,
testID,
}: DiffScrollProps) {
const horizontalScroll = useHorizontalScrollOptional();
const [isAtLeftEdge, setIsAtLeftEdge] = useState(true);
const scrollId = useId();
const closeGestureRef = useFileExplorerCloseGestureRef();
useLayoutEffect(() => {
horizontalScroll?.registerScrollOffset(scrollId, 0);
return () => horizontalScroll?.unregisterScrollOffset(scrollId);
}, [horizontalScroll, scrollId]);
const handleScroll = useCallback(
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
const offsetX = event.nativeEvent.contentOffset.x;
offset.value = offsetX;
setIsAtLeftEdge(offsetX <= 1);
horizontalScroll?.registerScrollOffset(scrollId, offsetX);
},
[horizontalScroll, offset, scrollId],
);
const handleLayout = useCallback(
(e: LayoutChangeEvent) => onScrollViewWidthChange(e.nativeEvent.layout.width),
(event: LayoutChangeEvent) => onScrollViewWidthChange(event.nativeEvent.layout.width),
[onScrollViewWidthChange],
);
@@ -25,9 +58,14 @@ export function DiffScroll({
horizontal
nestedScrollEnabled
showsHorizontalScrollIndicator
bounces={false}
style={style}
contentContainerStyle={contentContainerStyle}
onScroll={handleScroll}
scrollEventThrottle={16}
onLayout={handleLayout}
testID={testID}
waitFor={isAtLeftEdge && closeGestureRef?.current ? closeGestureRef : undefined}
>
{children}
</ScrollView>