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

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

SettingsScreen.tsxBlame347 lines · 1 contributor
9a8fbedClaude1import React, { useCallback, useState } from 'react';
2import {
3 Alert,
4 ScrollView,
5 StyleSheet,
6 Switch,
7 Text,
8 TextInput,
9 TouchableOpacity,
10 View,
11} from 'react-native';
12import { SafeAreaView } from 'react-native-safe-area-context';
13import { useAuth } from '../hooks/useAuth';
14import { useSettingsStore } from '../store/settingsStore';
15import { colors } from '../theme/colors';
16
17export function SettingsScreen(): React.ReactElement {
18 const { user, logout } = useAuth();
19 const { host, setHost, notificationsEnabled, setNotificationsEnabled } =
20 useSettingsStore();
21
22 const [hostInput, setHostInput] = useState(host);
23 const [hostSaved, setHostSaved] = useState(false);
24
25 const handleSaveHost = useCallback(() => {
26 const trimmed = hostInput.trim().replace(/\/$/, '');
27 if (!trimmed) return;
28 setHost(trimmed);
29 setHostSaved(true);
30 setTimeout(() => setHostSaved(false), 2000);
31 }, [hostInput, setHost]);
32
33 const handleLogout = useCallback(() => {
34 Alert.alert(
35 'Sign Out',
36 'Are you sure you want to sign out?',
37 [
38 { text: 'Cancel', style: 'cancel' },
39 {
40 text: 'Sign Out',
41 style: 'destructive',
42 onPress: () => logout(),
43 },
44 ],
45 );
46 }, [logout]);
47
48 return (
49 <SafeAreaView style={styles.safe} edges={['top', 'bottom']}>
50 <ScrollView showsVerticalScrollIndicator={false}>
51 {/* Header */}
52 <View style={styles.pageHeader}>
53 <Text style={styles.pageTitle}>Settings</Text>
54 </View>
55
56 {/* Account section */}
57 <View style={styles.section}>
58 <Text style={styles.sectionTitle}>Account</Text>
59 <View style={styles.card}>
60 <View style={styles.accountRow}>
61 <View style={styles.avatar}>
62 <Text style={styles.avatarText}>
63 {user?.username.charAt(0).toUpperCase() ?? '?'}
64 </Text>
65 </View>
66 <View style={styles.accountInfo}>
67 <Text style={styles.username}>{user?.username ?? 'Unknown'}</Text>
68 <Text style={styles.email}>{user?.email ?? ''}</Text>
69 </View>
70 </View>
71 </View>
72 </View>
73
74 {/* Connection section */}
75 <View style={styles.section}>
76 <Text style={styles.sectionTitle}>Connection</Text>
77 <View style={styles.card}>
78 <View style={styles.formGroup}>
79 <Text style={styles.label}>Host URL</Text>
80 <View style={styles.inputRow}>
81 <TextInput
82 style={styles.input}
83 value={hostInput}
84 onChangeText={setHostInput}
85 placeholder="https://gluecron.com"
86 placeholderTextColor={colors.textMuted}
87 autoCapitalize="none"
88 autoCorrect={false}
89 keyboardType="url"
90 />
91 <TouchableOpacity
92 style={[styles.saveButton, hostSaved && styles.saveButtonSaved]}
93 onPress={handleSaveHost}
94 activeOpacity={0.8}
95 >
96 <Text style={styles.saveButtonText}>
97 {hostSaved ? '✓ Saved' : 'Save'}
98 </Text>
99 </TouchableOpacity>
100 </View>
101 <Text style={styles.hint}>
102 Current: {host}
103 </Text>
104 </View>
105 </View>
106 </View>
107
108 {/* Preferences section */}
109 <View style={styles.section}>
110 <Text style={styles.sectionTitle}>Preferences</Text>
111 <View style={styles.card}>
112 <View style={styles.toggleRow}>
113 <View>
114 <Text style={styles.toggleLabel}>Notifications</Text>
115 <Text style={styles.toggleDesc}>
116 Show notification badges
117 </Text>
118 </View>
119 <Switch
120 value={notificationsEnabled}
121 onValueChange={setNotificationsEnabled}
122 trackColor={{ false: colors.bgTertiary, true: colors.accent }}
123 thumbColor={colors.text}
124 />
125 </View>
126 </View>
127 </View>
128
129 {/* About section */}
130 <View style={styles.section}>
131 <Text style={styles.sectionTitle}>About</Text>
132 <View style={styles.card}>
133 <View style={styles.aboutRow}>
134 <Text style={styles.aboutLabel}>App Version</Text>
135 <Text style={styles.aboutValue}>1.0.0</Text>
136 </View>
137 <View style={[styles.aboutRow, styles.aboutRowBorder]}>
138 <Text style={styles.aboutLabel}>Platform</Text>
139 <Text style={styles.aboutValue}>Gluecron Mobile</Text>
140 </View>
141 <View style={[styles.aboutRow, styles.aboutRowBorder]}>
142 <Text style={styles.aboutLabel}>Connected to</Text>
143 <Text style={styles.aboutValue} numberOfLines={1}>
144 {host}
145 </Text>
146 </View>
147 </View>
148 </View>
149
150 {/* Danger zone */}
151 <View style={styles.section}>
152 <TouchableOpacity
153 style={styles.logoutButton}
154 onPress={handleLogout}
155 activeOpacity={0.8}
156 >
157 <Text style={styles.logoutText}>Sign Out</Text>
158 </TouchableOpacity>
159 </View>
160
161 <View style={styles.footer}>
162 <Text style={styles.footerText}>
163 Gluecron — AI-native code intelligence platform
164 </Text>
165 <Text style={styles.footerText}>gluecron.com</Text>
166 </View>
167 </ScrollView>
168 </SafeAreaView>
169 );
170}
171
172const styles = StyleSheet.create({
173 safe: {
174 flex: 1,
175 backgroundColor: colors.bg,
176 },
177 pageHeader: {
178 paddingHorizontal: 16,
179 paddingVertical: 16,
180 backgroundColor: colors.bgSecondary,
181 borderBottomWidth: 1,
182 borderBottomColor: colors.border,
183 },
184 pageTitle: {
185 fontSize: 20,
186 fontWeight: '700',
187 color: colors.text,
188 },
189 section: {
190 marginTop: 24,
191 paddingHorizontal: 16,
192 gap: 8,
193 },
194 sectionTitle: {
195 fontSize: 12,
196 fontWeight: '600',
197 color: colors.textMuted,
198 textTransform: 'uppercase',
199 letterSpacing: 0.5,
200 marginBottom: 4,
201 },
202 card: {
203 backgroundColor: colors.bgSecondary,
204 borderRadius: 10,
205 borderWidth: 1,
206 borderColor: colors.border,
207 overflow: 'hidden',
208 },
209 accountRow: {
210 flexDirection: 'row',
211 alignItems: 'center',
212 padding: 14,
213 gap: 12,
214 },
215 avatar: {
216 width: 48,
217 height: 48,
218 borderRadius: 24,
219 backgroundColor: colors.accentBlue,
220 alignItems: 'center',
221 justifyContent: 'center',
222 },
223 avatarText: {
224 fontSize: 20,
225 fontWeight: '700',
226 color: colors.bg,
227 },
228 accountInfo: {
229 gap: 3,
230 },
231 username: {
232 fontSize: 16,
233 fontWeight: '600',
234 color: colors.text,
235 },
236 email: {
237 fontSize: 13,
238 color: colors.textMuted,
239 },
240 formGroup: {
241 padding: 14,
242 gap: 8,
243 },
244 label: {
245 fontSize: 12,
246 fontWeight: '500',
247 color: colors.textMuted,
248 textTransform: 'uppercase',
249 letterSpacing: 0.4,
250 },
251 inputRow: {
252 flexDirection: 'row',
253 gap: 8,
254 alignItems: 'center',
255 },
256 input: {
257 flex: 1,
258 backgroundColor: colors.bg,
259 borderWidth: 1,
260 borderColor: colors.border,
261 borderRadius: 8,
262 paddingHorizontal: 12,
263 paddingVertical: 10,
264 fontSize: 14,
265 color: colors.text,
266 },
267 saveButton: {
268 paddingHorizontal: 14,
269 paddingVertical: 10,
270 backgroundColor: colors.bgTertiary,
271 borderRadius: 8,
272 borderWidth: 1,
273 borderColor: colors.border,
274 },
275 saveButtonSaved: {
276 borderColor: colors.accent,
277 },
278 saveButtonText: {
279 fontSize: 13,
280 fontWeight: '600',
281 color: colors.textLink,
282 },
283 hint: {
284 fontSize: 12,
285 color: colors.textMuted,
286 },
287 toggleRow: {
288 flexDirection: 'row',
289 alignItems: 'center',
290 justifyContent: 'space-between',
291 padding: 14,
292 },
293 toggleLabel: {
294 fontSize: 15,
295 fontWeight: '500',
296 color: colors.text,
297 },
298 toggleDesc: {
299 fontSize: 12,
300 color: colors.textMuted,
301 marginTop: 2,
302 },
303 aboutRow: {
304 flexDirection: 'row',
305 alignItems: 'center',
306 justifyContent: 'space-between',
307 paddingVertical: 12,
308 paddingHorizontal: 14,
309 },
310 aboutRowBorder: {
311 borderTopWidth: 1,
312 borderTopColor: colors.border,
313 },
314 aboutLabel: {
315 fontSize: 14,
316 color: colors.textMuted,
317 },
318 aboutValue: {
319 fontSize: 14,
320 color: colors.text,
321 maxWidth: '60%',
322 textAlign: 'right',
323 },
324 logoutButton: {
325 backgroundColor: colors.bgSecondary,
326 borderRadius: 10,
327 borderWidth: 1,
328 borderColor: colors.accentRed,
329 paddingVertical: 14,
330 alignItems: 'center',
331 },
332 logoutText: {
333 fontSize: 15,
334 fontWeight: '600',
335 color: colors.accentRed,
336 },
337 footer: {
338 padding: 32,
339 alignItems: 'center',
340 gap: 4,
341 },
342 footerText: {
343 fontSize: 12,
344 color: colors.textMuted,
345 textAlign: 'center',
346 },
347});