Add desktop web scrollbar handles to file preview pane

This commit is contained in:
Mohamed Boudra
2026-02-19 09:55:08 +07:00
parent 24a8db5763
commit b6b0933a39
@@ -685,7 +685,12 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
</View> </View>
</View> </View>
<FilePreviewBody preview={preview} isLoading={isPreviewLoading} variant="inline" /> <FilePreviewBody
preview={preview}
isLoading={isPreviewLoading}
variant="inline"
showDesktopWebScrollbar={showDesktopWebScrollbar}
/>
</View> </View>
) : null} ) : null}
@@ -853,7 +858,12 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
<X size={20} color={theme.colors.foregroundMuted} /> <X size={20} color={theme.colors.foregroundMuted} />
</Pressable> </Pressable>
</View> </View>
<FilePreviewBody preview={preview} isLoading={isPreviewLoading} variant="sheet" /> <FilePreviewBody
preview={preview}
isLoading={isPreviewLoading}
variant="sheet"
showDesktopWebScrollbar={false}
/>
</BottomSheetModal> </BottomSheetModal>
) : null} ) : null}
</View> </View>
@@ -864,11 +874,36 @@ function FilePreviewBody({
preview, preview,
isLoading, isLoading,
variant, variant,
showDesktopWebScrollbar,
}: { }: {
preview: ExplorerFile | null; preview: ExplorerFile | null;
isLoading: boolean; isLoading: boolean;
variant: "inline" | "sheet"; variant: "inline" | "sheet";
showDesktopWebScrollbar: boolean;
}) { }) {
const enablePreviewDesktopScrollbar =
variant === "inline" && showDesktopWebScrollbar;
const previewScrollRef = useRef<RNScrollView>(null);
const previewScrollbarMetrics = useWebDesktopScrollbarMetrics();
const handlePreviewScroll = useCallback(
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
if (enablePreviewDesktopScrollbar) {
previewScrollbarMetrics.onScroll(event);
}
},
[enablePreviewDesktopScrollbar, previewScrollbarMetrics]
);
const handlePreviewLayout = useCallback(
(event: LayoutChangeEvent) => {
if (enablePreviewDesktopScrollbar) {
previewScrollbarMetrics.onLayout(event);
}
},
[enablePreviewDesktopScrollbar, previewScrollbarMetrics]
);
if (isLoading && !preview) { if (isLoading && !preview) {
return ( return (
<View style={styles.sheetCenterState}> <View style={styles.sheetCenterState}>
@@ -902,16 +937,37 @@ function FilePreviewBody({
); );
} }
return ( return (
<RNScrollView style={styles.previewContent}> <View style={styles.previewScrollContainer}>
<RNScrollView <RNScrollView
horizontal ref={previewScrollRef}
nestedScrollEnabled style={styles.previewContent}
showsHorizontalScrollIndicator onLayout={enablePreviewDesktopScrollbar ? handlePreviewLayout : undefined}
contentContainerStyle={styles.previewCodeScrollContent} onScroll={enablePreviewDesktopScrollbar ? handlePreviewScroll : undefined}
onContentSizeChange={
enablePreviewDesktopScrollbar
? previewScrollbarMetrics.onContentSizeChange
: undefined
}
scrollEventThrottle={enablePreviewDesktopScrollbar ? 16 : undefined}
showsVerticalScrollIndicator={!enablePreviewDesktopScrollbar}
> >
<Text style={styles.codeText}>{preview.content}</Text> <RNScrollView
horizontal
nestedScrollEnabled
showsHorizontalScrollIndicator
contentContainerStyle={styles.previewCodeScrollContent}
>
<Text style={styles.codeText}>{preview.content}</Text>
</RNScrollView>
</RNScrollView> </RNScrollView>
</RNScrollView> <WebDesktopScrollbarOverlay
enabled={enablePreviewDesktopScrollbar}
metrics={previewScrollbarMetrics}
onScrollToOffset={(nextOffset) => {
previewScrollRef.current?.scrollTo({ y: nextOffset, animated: false });
}}
/>
</View>
); );
} }
@@ -930,15 +986,37 @@ function FilePreviewBody({
); );
} }
return ( return (
<RNScrollView contentContainerStyle={styles.previewImageScrollContent}> <View style={styles.previewScrollContainer}>
<RNImage <RNScrollView
source={{ ref={previewScrollRef}
uri: `data:${preview.mimeType ?? "image/png"};base64,${preview.content}`, style={styles.previewContent}
contentContainerStyle={styles.previewImageScrollContent}
onLayout={enablePreviewDesktopScrollbar ? handlePreviewLayout : undefined}
onScroll={enablePreviewDesktopScrollbar ? handlePreviewScroll : undefined}
onContentSizeChange={
enablePreviewDesktopScrollbar
? previewScrollbarMetrics.onContentSizeChange
: undefined
}
scrollEventThrottle={enablePreviewDesktopScrollbar ? 16 : undefined}
showsVerticalScrollIndicator={!enablePreviewDesktopScrollbar}
>
<RNImage
source={{
uri: `data:${preview.mimeType ?? "image/png"};base64,${preview.content}`,
}}
style={styles.previewImage}
resizeMode="contain"
/>
</RNScrollView>
<WebDesktopScrollbarOverlay
enabled={enablePreviewDesktopScrollbar}
metrics={previewScrollbarMetrics}
onScrollToOffset={(nextOffset) => {
previewScrollRef.current?.scrollTo({ y: nextOffset, animated: false });
}} }}
style={styles.previewImage}
resizeMode="contain"
/> />
</RNScrollView> </View>
); );
} }
@@ -1377,6 +1455,11 @@ const styles = StyleSheet.create((theme) => ({
previewContent: { previewContent: {
flex: 1, flex: 1,
}, },
previewScrollContainer: {
flex: 1,
minHeight: 0,
position: "relative",
},
previewCodeScrollContent: { previewCodeScrollContent: {
paddingTop: theme.spacing[3], paddingTop: theme.spacing[3],
paddingHorizontal: theme.spacing[3], paddingHorizontal: theme.spacing[3],