Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

CommitsScreen.tsx

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

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