import { ActivityIndicator, Pressable, Text, View } from 'react-native' import { ChevronRight, FileText, Minus, Plus, Trash2 } from 'lucide-react-native' import type { SectionListRenderItem } from 'react-native' import { colors } from '../theme/mobile-theme' import { MOBILE_GIT_STATUS_LABELS, type MobileSourceControlSection } from './mobile-git-status' import { formatMobileBranchEntryMeta } from './mobile-branch-entry-format' import { statusColor, type MobileGitStatusEntryView } from './mobile-source-control-screen-state' import type { MobileSourceControlState } from './use-mobile-source-control-state' import { styles } from './mobile-source-control-styles' type RowState = Pick< MobileSourceControlState, | 'busyAction' | 'openingPath' | 'openingBranchPath' | 'openFile' | 'runGitAction' | 'setDiscardTarget' > export function makeRenderFileRow( state: RowState ): SectionListRenderItem< MobileGitStatusEntryView, MobileSourceControlSection > { const { busyAction, openingPath, openingBranchPath, openFile, runGitAction, setDiscardTarget } = state return function FileRow({ item }) { const rowBusy = busyAction === item.stageActionId || busyAction === item.unstageActionId || busyAction === item.discardActionId || openingPath === item.path const rowDisabled = !item.canOpen || busyAction !== null || openingPath !== null || openingBranchPath !== null const ioBusy = busyAction !== null || openingPath !== null || openingBranchPath !== null return ( [ styles.fileRow, pressed && item.canOpen && styles.fileRowPressed, rowDisabled && styles.fileRowDisabled, !item.canOpen && styles.fileRowUnavailable ]} onPress={() => void openFile(item)} disabled={rowDisabled} accessibilityLabel={`Open changed file ${item.path}`} > {MOBILE_GIT_STATUS_LABELS[item.status]} {item.path} {item.oldPath ? ( from {item.oldPath} ) : item.conflictStatus === 'unresolved' ? ( Unresolved conflict ) : null} {rowBusy ? ( ) : item.area === 'staged' ? ( [ styles.iconButton, ioBusy && styles.iconButtonDisabled, pressed && styles.iconButtonPressed ]} disabled={ioBusy} onPress={() => void runGitAction(item.unstageActionId, 'git.unstage', { filePath: item.path }) } hitSlop={8} accessibilityLabel={`Unstage ${item.path}`} > ) : item.canStage || item.canDiscard ? ( {item.canStage ? ( [ styles.iconButton, ioBusy && styles.iconButtonDisabled, pressed && styles.iconButtonPressed ]} disabled={ioBusy} onPress={() => void runGitAction(item.stageActionId, 'git.stage', { filePath: item.path }) } hitSlop={8} accessibilityLabel={`Stage ${item.path}`} > ) : null} {item.canDiscard ? ( [ styles.iconButton, ioBusy && styles.iconButtonDisabled, pressed && styles.iconButtonPressed ]} disabled={ioBusy} onPress={() => setDiscardTarget(item)} hitSlop={8} accessibilityLabel={`Discard ${item.path}`} > ) : null} ) : null} {!rowBusy && item.canOpen ? ( ) : null} ) } } type FooterState = Pick< MobileSourceControlState, | 'shouldShowBranchCompareSection' | 'branchCompareSummaryText' | 'branchEntries' | 'branchCompareState' | 'branchCompareResult' | 'busyAction' | 'openBranchDiff' | 'openingBranchPath' | 'openingPath' > export function BranchCompareFooter({ state }: { state: FooterState }) { const { shouldShowBranchCompareSection, branchCompareSummaryText, branchEntries, branchCompareState, branchCompareResult, busyAction, openBranchDiff, openingBranchPath, openingPath } = state if (!shouldShowBranchCompareSection) { return null } return ( Committed on Branch {branchCompareSummaryText ? ( {branchCompareSummaryText} ) : null} {branchEntries.length} {branchCompareState.kind === 'loading' ? ( Loading committed changes... ) : branchCompareState.kind === 'error' ? ( {branchCompareState.message} ) : branchCompareResult && branchCompareResult.summary.status !== 'ready' ? ( {branchCompareResult.summary.errorMessage ?? 'Committed changes unavailable.'} ) : ( branchEntries.map((entry) => { const rowBusy = openingBranchPath === entry.path const rowDisabled = !entry.canOpen || busyAction !== null || openingPath !== null || openingBranchPath !== null const meta = formatMobileBranchEntryMeta(entry) return ( [ styles.fileRow, pressed && entry.canOpen && styles.fileRowPressed, rowDisabled && styles.fileRowDisabled, !entry.canOpen && styles.fileRowUnavailable ]} onPress={() => void openBranchDiff(entry)} disabled={rowDisabled} accessibilityLabel={`Open committed change ${entry.path}`} > {MOBILE_GIT_STATUS_LABELS[entry.status]} {entry.path} {meta ? ( {meta} ) : null} {rowBusy ? ( ) : entry.canOpen ? ( ) : null} ) }) )} ) }