import { ActivityIndicator, Pressable, SectionList, Text, TextInput, View } from 'react-native'
import { GitBranch, Minus, MoreHorizontal, Plus, Sparkles } from 'lucide-react-native'
import { colors, spacing } from '../theme/mobile-theme'
import { MobileSourceControlReviewEntry } from './mobile-source-control-review-entry'
import { KEYBOARD_COMMIT_BAR_CLEARANCE } from './mobile-source-control-screen-state'
import { makeRenderFileRow, BranchCompareFooter } from './MobileSourceControlFileRows'
import type { MobileSourceControlState } from './use-mobile-source-control-state'
import { styles } from './mobile-source-control-styles'
type Props = {
state: MobileSourceControlState
hostId: string
worktreeId: string
name: string
}
// The ready-state body: summary card, changed-files list, and commit bar.
export function MobileSourceControlContent({ state, hostId, worktreeId, name }: Props) {
const {
connState,
insets,
screenState,
busyAction,
commitMessage,
setCommitMessage,
generatingMessage,
setShowActionSheet,
setDiscardTarget,
actionError,
keyboardLift,
openingPath,
openingBranchPath,
status,
sections,
branchEntries,
hasVisibleChanges,
reviewableCount,
stageablePaths,
unstageablePaths,
stagedCount,
unstagedCount,
branchLabel,
syncLabel,
primaryAction,
stageAll,
unstageAll,
generateCommitMessage,
cancelGenerateCommitMessage,
abortConflictOperation,
openFile,
openBranchDiff,
runGitAction
} = state
const ioBusy = busyAction !== null || openingPath !== null || openingBranchPath !== null
const shouldShowGenerateButton = stagedCount > 0 || generatingMessage
return (
<>
{branchLabel}
{syncLabel ? {syncLabel} : null}
{unstagedCount} changed
{stagedCount} staged
{branchEntries.length > 0 ? (
{branchEntries.length} on branch
) : null}
{status && status.conflictOperation !== 'unknown' ? (
{status.conflictOperation}
{(status.conflictOperation === 'merge' || status.conflictOperation === 'rebase') && (
[styles.abortButton, pressed && styles.abortPressed]}
disabled={busyAction !== null}
onPress={() => void abortConflictOperation(status.conflictOperation)}
>
{busyAction === `abort-${status.conflictOperation}`
? 'Aborting…'
: `Abort ${status.conflictOperation}`}
)}
) : null}
{actionError ? (
{actionError}
) : null}
[
styles.bulkButton,
(stageablePaths.length === 0 || ioBusy) && styles.bulkButtonDisabled,
pressed && styles.bulkButtonPressed
]}
onPress={() => void stageAll()}
disabled={ioBusy || stageablePaths.length === 0}
>
{busyAction === 'stage-all' ? (
) : (
)}
Stage All
[
styles.bulkButton,
(unstageablePaths.length === 0 || ioBusy) && styles.bulkButtonDisabled,
pressed && styles.bulkButtonPressed
]}
onPress={() => void unstageAll()}
disabled={ioBusy || unstageablePaths.length === 0}
>
{busyAction === 'unstage-all' ? (
) : (
)}
Unstage All
[
styles.bulkMenuButton,
pressed && styles.bulkButtonPressed,
ioBusy && styles.bulkButtonDisabled
]}
onPress={() => setShowActionSheet(true)}
disabled={ioBusy}
hitSlop={8}
accessibilityLabel="Open source control actions"
>
{!hasVisibleChanges ? (
No Changes
Working tree is clean.
) : (
`${item.area}:${item.path}:${item.oldPath ?? ''}`}
renderSectionHeader={({ section }) => (
{section.title}
{section.data.length}
)}
ListFooterComponent={
}
stickySectionHeadersEnabled={false}
contentContainerStyle={styles.listContent}
/>
)}
0 ? keyboardLift + KEYBOARD_COMMIT_BAR_CLEARANCE : keyboardLift,
paddingBottom: keyboardLift > 0 ? spacing.md : spacing.md + insets.bottom
}
]}
>
{stagedCount === 0 ? (
No staged files
) : (
)}
{shouldShowGenerateButton ? (
[
styles.generateButton,
busyAction !== null && styles.commitButtonDisabled,
pressed && styles.commitButtonPressed
]}
// Why: commit-message AI belongs to the commit path; hiding it
// during Stage All keeps the quick action visually unambiguous.
disabled={busyAction !== null}
onPress={() =>
generatingMessage ? cancelGenerateCommitMessage() : void generateCommitMessage()
}
accessibilityLabel={
generatingMessage
? 'Cancel commit message generation'
: 'Generate commit message with AI'
}
>
{generatingMessage ? (
) : (
)}
) : null}
[
styles.commitButton,
primaryAction.disabled && styles.commitButtonDisabled,
pressed && styles.commitButtonPressed
]}
onPress={primaryAction.onPress}
disabled={primaryAction.disabled}
accessibilityLabel={primaryAction.accessibilityLabel}
accessibilityHint={primaryAction.accessibilityHint}
>
{primaryAction.loading ? (
) : (
{primaryAction.label}
)}
>
)
}