import { useState, useCallback, useEffect, useId, useRef } from "react"; import { type LayoutChangeEvent, type NativeSyntheticEvent, type NativeScrollEvent, type StyleProp, type ViewStyle, } from "react-native"; import { ScrollView, type ScrollView as ScrollViewType } from "react-native-gesture-handler"; import { useHorizontalScrollOptional } from "@/contexts/horizontal-scroll-context"; import { useExplorerSidebarAnimationOptional } from "@/contexts/explorer-sidebar-animation-context"; interface DiffScrollProps { children: React.ReactNode; scrollViewWidth: number; onScrollViewWidthChange: (width: number) => void; style?: StyleProp; contentContainerStyle?: StyleProp; } export function DiffScroll({ children, scrollViewWidth: _scrollViewWidth, onScrollViewWidthChange, style, contentContainerStyle, }: DiffScrollProps) { const [isAtLeftEdge, setIsAtLeftEdge] = useState(true); const horizontalScroll = useHorizontalScrollOptional(); const scrollId = useId(); const scrollViewRef = useRef(null); // Get the close gesture ref from animation context (may not be available outside sidebar) const animation = useExplorerSidebarAnimationOptional(); const closeGestureRef = animation?.closeGestureRef; // Register/unregister scroll offset tracking useEffect(() => { if (!horizontalScroll) return; // Start at 0 (not scrolled) horizontalScroll.registerScrollOffset(scrollId, 0); return () => { horizontalScroll.unregisterScrollOffset(scrollId); }; }, [horizontalScroll, scrollId]); const handleScroll = useCallback( (event: NativeSyntheticEvent) => { const offsetX = event.nativeEvent.contentOffset.x; // Track if we're at the left edge (with small threshold for float precision) setIsAtLeftEdge(offsetX <= 1); if (horizontalScroll) { horizontalScroll.registerScrollOffset(scrollId, offsetX); } }, [horizontalScroll, scrollId], ); const handleLayout = useCallback( (e: LayoutChangeEvent) => onScrollViewWidthChange(e.nativeEvent.layout.width), [onScrollViewWidthChange], ); return ( {children} ); }