1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
| import React, { useCallback } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import { useCommits } from '../hooks/useRepo';
import { CommitRow } from '../components/CommitRow';
import { LoadingSpinner } from '../components/LoadingSpinner';
import { ErrorBanner } from '../components/ErrorBanner';
import { colors } from '../theme/colors';
import type { RepoStackParamList } from '../navigation/AppNavigator';
import type { CommitEntry } from '../api/repos';
type Props = NativeStackScreenProps<RepoStackParamList, 'Commits'>;
export function CommitsScreen({ route }: Props): React.ReactElement {
const { owner, repo, branch } = route.params;
const { commits, isLoading, error, loadMore, hasMore } = useCommits(
owner,
repo,
branch ?? 'HEAD',
);
const renderCommit = useCallback(
({ item }: { item: CommitEntry }) => <CommitRow commit={item} />,
[],
);
const keyExtractor = useCallback((item: CommitEntry) => item.sha, []);
const renderFooter = useCallback(() => {
if (!hasMore) return null;
return <LoadingSpinner size="small" />;
}, [hasMore]);
if (isLoading && commits.length === 0) return <LoadingSpinner fullScreen />;
return (
<SafeAreaView style={styles.safe} edges={['bottom']}>
{error !== null && <ErrorBanner message={error} />}
<FlatList
data={commits}
keyExtractor={keyExtractor}
renderItem={renderCommit}
onEndReached={loadMore}
onEndReachedThreshold={0.3}
ListFooterComponent={renderFooter}
ListEmptyComponent={
<View style={styles.emptyState}>
<Text style={styles.emptyText}>No commits found</Text>
</View>
}
ListHeaderComponent={
<View style={styles.header}>
<Text style={styles.headerText}>
{branch ?? 'HEAD'} — commit history
</Text>
</View>
}
style={styles.list}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: {
flex: 1,
backgroundColor: colors.bg,
},
list: {
flex: 1,
},
header: {
padding: 12,
backgroundColor: colors.bgTertiary,
borderBottomWidth: 1,
borderBottomColor: colors.border,
},
headerText: {
fontSize: 12,
fontFamily: 'monospace',
color: colors.textMuted,
},
emptyState: {
padding: 40,
alignItems: 'center',
},
emptyText: {
fontSize: 14,
color: colors.textMuted,
},
});
|