Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

IssueListScreen.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.

IssueListScreen.tsxBlame149 lines · 1 contributor
c53cf00Claude1import React, { useState } from 'react';
2import {
3 View,
4 Text,
5 FlatList,
6 StyleSheet,
7 RefreshControl,
8 TouchableOpacity,
9} from 'react-native';
10import { SafeAreaView } from 'react-native-safe-area-context';
11import { type NativeStackNavigationProp } from '@react-navigation/native-stack';
12import { type RouteProp } from '@react-navigation/native';
13import { colors } from '../theme/colors';
14import { fontSizes, fontWeights } from '../theme/typography';
15import { useIssues } from '../hooks/useIssues';
16import { IssueRow } from '../components/IssueRow';
17import { LoadingSpinner } from '../components/LoadingSpinner';
18import { ErrorState } from '../components/ErrorState';
19import { EmptyState } from '../components/EmptyState';
9d7a803Claude20import { type MainStackParamList } from '../navigation/types';
c53cf00Claude21
22type Props = {
23 navigation: NativeStackNavigationProp<MainStackParamList, 'IssueList'>;
24 route: RouteProp<MainStackParamList, 'IssueList'>;
25};
26
27export function IssueListScreen({ navigation, route }: Props) {
28 const { owner, repo } = route.params;
29 const [stateFilter, setStateFilter] = useState<'open' | 'closed'>('open');
30 const [refreshing, setRefreshing] = useState(false);
31 const { issues, loading, error, refresh } = useIssues(owner, repo, stateFilter);
32
33 async function onRefresh() {
34 setRefreshing(true);
35 await refresh();
36 setRefreshing(false);
37 }
38
39 if (loading && !refreshing && issues.length === 0) {
40 return <LoadingSpinner fullScreen />;
41 }
42
43 if (error && issues.length === 0) {
44 return <ErrorState message={error} onRetry={refresh} />;
45 }
46
47 return (
48 <SafeAreaView style={styles.safe} edges={['top']}>
49 {/* State toggle */}
50 <View style={styles.toggleBar}>
51 <TouchableOpacity
52 style={[styles.toggleBtn, stateFilter === 'open' && styles.toggleActive]}
53 onPress={() => setStateFilter('open')}
54 activeOpacity={0.75}
55 >
56 <View style={[styles.dot, { backgroundColor: colors.green }]} />
57 <Text style={[styles.toggleText, stateFilter === 'open' && styles.toggleTextActive]}>
58 Open
59 </Text>
60 </TouchableOpacity>
61 <TouchableOpacity
62 style={[styles.toggleBtn, stateFilter === 'closed' && styles.toggleActive]}
63 onPress={() => setStateFilter('closed')}
64 activeOpacity={0.75}
65 >
66 <View style={[styles.dot, { backgroundColor: colors.textMuted }]} />
67 <Text style={[styles.toggleText, stateFilter === 'closed' && styles.toggleTextActive]}>
68 Closed
69 </Text>
70 </TouchableOpacity>
71 <Text style={styles.repoBadge}>{owner}/{repo}</Text>
72 </View>
73
74 <FlatList
75 data={issues}
76 keyExtractor={(item) => item.id}
77 renderItem={({ item }) => (
78 <IssueRow
79 issue={item}
80 onPress={() =>
81 navigation.navigate('IssueDetail', {
82 owner,
83 repo,
84 number: item.number,
85 })
86 }
87 />
88 )}
89 refreshControl={
90 <RefreshControl refreshing={refreshing} onRefresh={onRefresh} tintColor={colors.accent} />
91 }
92 ListEmptyComponent={
93 <EmptyState
94 title={`No ${stateFilter} issues`}
95 subtitle="Issues will appear here when created"
96 icon="●"
97 />
98 }
99 />
100 </SafeAreaView>
101 );
102}
103
104const styles = StyleSheet.create({
105 safe: {
106 flex: 1,
107 backgroundColor: colors.bg,
108 },
109 toggleBar: {
110 flexDirection: 'row',
111 alignItems: 'center',
112 padding: 12,
113 gap: 8,
114 borderBottomWidth: 1,
115 borderBottomColor: colors.border,
116 },
117 toggleBtn: {
118 flexDirection: 'row',
119 alignItems: 'center',
120 gap: 6,
121 paddingHorizontal: 12,
122 paddingVertical: 6,
123 borderRadius: 20,
124 borderWidth: 1,
125 borderColor: 'transparent',
126 },
127 toggleActive: {
128 borderColor: colors.border,
129 backgroundColor: colors.bgSurface,
130 },
131 dot: {
132 width: 8,
133 height: 8,
134 borderRadius: 4,
135 },
136 toggleText: {
137 color: colors.textMuted,
138 fontSize: fontSizes.sm,
139 fontWeight: fontWeights.medium,
140 },
141 toggleTextActive: {
142 color: colors.text,
143 },
144 repoBadge: {
145 marginLeft: 'auto',
146 color: colors.textMuted,
147 fontSize: fontSizes.xs,
148 },
149});