import React from "react"; import { View, Text, Platform, ScrollView as RNScrollView } from "react-native"; import { ScrollView as GHScrollView } from "react-native-gesture-handler"; import { StyleSheet } from "react-native-unistyles"; import { Fonts } from "@/constants/theme"; import type { DiffLine, DiffSegment } from "@/utils/tool-call-parsers"; import { getCodeInsets } from "./code-insets"; const ScrollView = Platform.OS === "web" ? RNScrollView : GHScrollView; interface DiffViewerProps { diffLines: DiffLine[]; maxHeight?: number; emptyLabel?: string; fillAvailableHeight?: boolean; } export function DiffViewer({ diffLines, maxHeight, emptyLabel = "No changes to display", fillAvailableHeight = false, }: DiffViewerProps) { const [scrollViewWidth, setScrollViewWidth] = React.useState(0); if (!diffLines.length) { return ( {emptyLabel} ); } return ( setScrollViewWidth(e.nativeEvent.layout.width)} > 0 && { minWidth: scrollViewWidth }]}> {diffLines.map((line, index) => ( {line.segments ? ( {line.content[0]} {line.segments.map((segment, segIdx) => ( {segment.text} ))} ) : ( {line.content} )} ))} ); } const styles = StyleSheet.create((theme) => { const insets = getCodeInsets(theme); return { verticalScroll: {}, fillHeight: { flex: 1, minHeight: 0, }, verticalContent: { flexGrow: 1, paddingBottom: insets.extraBottom, }, horizontalContent: { flexDirection: "column" as const, paddingRight: insets.extraRight, }, linesContainer: { alignSelf: "flex-start", padding: insets.padding, }, line: { minWidth: "100%", paddingHorizontal: 0, paddingVertical: theme.spacing[1], }, lineText: { fontFamily: Fonts.mono, fontSize: theme.fontSize.xs, color: theme.colors.foreground, ...(Platform.OS === "web" ? { whiteSpace: "pre", overflowWrap: "normal", } : null), }, headerLine: { backgroundColor: theme.colors.surface1, }, headerText: { color: theme.colors.foregroundMuted, }, addLine: { backgroundColor: "rgba(46, 160, 67, 0.15)", }, addText: { color: theme.colors.foreground, }, removeLine: { backgroundColor: "rgba(248, 81, 73, 0.1)", }, removeText: { color: theme.colors.foreground, }, addHighlight: { backgroundColor: "rgba(46, 160, 67, 0.4)", }, removeHighlight: { backgroundColor: "rgba(248, 81, 73, 0.35)", }, contextLine: { backgroundColor: theme.colors.surface1, }, contextText: { color: theme.colors.foregroundMuted, }, emptyState: { padding: theme.spacing[4], alignItems: "center" as const, justifyContent: "center" as const, }, emptyText: { fontSize: theme.fontSize.sm, color: theme.colors.foregroundMuted, }, }; });