Skip to content

Commit 4acbdf5

Browse files
committed
chore: Upgrade pnpm lockfile to version 9.0 and update dependencies
- Updated lockfile version from 6.0 to 9.0, reflecting changes in dependency management. - Reorganized dependencies under the new importers structure, ensuring compatibility with the latest pnpm features. - Updated various package versions to their latest compatible releases, enhancing overall project stability and performance.
1 parent 4030e26 commit 4acbdf5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+15040
-3839
lines changed

mobile/.gitignore

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2+
3+
# dependencies
4+
node_modules/
5+
6+
# Expo
7+
.expo/
8+
dist/
9+
web-build/
10+
expo-env.d.ts
11+
12+
# Native
13+
.kotlin/
14+
*.orig.*
15+
*.jks
16+
*.p8
17+
*.p12
18+
*.key
19+
*.mobileprovision
20+
21+
# Metro
22+
.metro-health-check*
23+
24+
# debug
25+
npm-debug.*
26+
yarn-debug.*
27+
yarn-error.*
28+
29+
# macOS
30+
.DS_Store
31+
*.pem
32+
33+
# local env files
34+
.env*.local
35+
36+
# typescript
37+
*.tsbuildinfo
38+
39+
# generated native folders
40+
/ios
41+
/android

mobile/app.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"expo": {
3+
"name": "WorldGuessr",
4+
"slug": "worldguessr",
5+
"version": "1.0.0",
6+
"orientation": "default",
7+
"icon": "./assets/icon.png",
8+
"userInterfaceStyle": "dark",
9+
"scheme": "worldguessr",
10+
"newArchEnabled": true,
11+
"splash": {
12+
"image": "./assets/splash-icon.png",
13+
"resizeMode": "contain",
14+
"backgroundColor": "#112b18"
15+
},
16+
"ios": {
17+
"supportsTablet": true,
18+
"bundleIdentifier": "com.worldguessr.app",
19+
"config": {
20+
"googleMapsApiKey": "YOUR_IOS_API_KEY"
21+
}
22+
},
23+
"android": {
24+
"adaptiveIcon": {
25+
"foregroundImage": "./assets/adaptive-icon.png",
26+
"backgroundColor": "#112b18"
27+
},
28+
"edgeToEdgeEnabled": true,
29+
"package": "com.worldguessr.app",
30+
"config": {
31+
"googleMaps": {
32+
"apiKey": "YOUR_ANDROID_API_KEY"
33+
}
34+
}
35+
},
36+
"web": {
37+
"favicon": "./assets/favicon.png",
38+
"bundler": "metro"
39+
},
40+
"plugins": [
41+
"expo-router",
42+
"expo-localization",
43+
"expo-secure-store",
44+
"expo-font"
45+
],
46+
"experiments": {
47+
"typedRoutes": true
48+
}
49+
}
50+
}

mobile/app/(auth)/_layout.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Stack } from 'expo-router';
2+
import { colors } from '../../src/shared';
3+
4+
export default function AuthLayout() {
5+
return (
6+
<Stack
7+
screenOptions={{
8+
headerShown: false,
9+
contentStyle: { backgroundColor: colors.background },
10+
}}
11+
>
12+
<Stack.Screen name="login" />
13+
<Stack.Screen name="set-username" />
14+
</Stack>
15+
);
16+
}

mobile/app/(auth)/login.tsx

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
import { useState } from 'react';
2+
import {
3+
View,
4+
Text,
5+
StyleSheet,
6+
Pressable,
7+
ActivityIndicator,
8+
Image,
9+
} from 'react-native';
10+
import { SafeAreaView } from 'react-native-safe-area-context';
11+
import { useRouter } from 'expo-router';
12+
import * as WebBrowser from 'expo-web-browser';
13+
import * as Google from 'expo-auth-session/providers/google';
14+
import { Ionicons } from '@expo/vector-icons';
15+
import { colors } from '../../src/shared';
16+
import { useAuthStore } from '../../src/store/authStore';
17+
import { GOOGLE_CLIENT_ID, GOOGLE_IOS_CLIENT_ID } from '../../src/constants/config';
18+
import { commonStyles, spacing, fontSizes, borderRadius } from '../../src/styles/theme';
19+
20+
WebBrowser.maybeCompleteAuthSession();
21+
22+
export default function LoginScreen() {
23+
const router = useRouter();
24+
const { loginWithGoogle, isLoading } = useAuthStore();
25+
const [error, setError] = useState<string | null>(null);
26+
27+
const [request, response, promptAsync] = Google.useIdTokenAuthRequest({
28+
clientId: GOOGLE_CLIENT_ID,
29+
iosClientId: GOOGLE_IOS_CLIENT_ID,
30+
});
31+
32+
const handleGoogleLogin = async () => {
33+
setError(null);
34+
35+
try {
36+
const result = await promptAsync();
37+
38+
if (result?.type === 'success') {
39+
const { id_token } = result.params;
40+
const success = await loginWithGoogle(id_token);
41+
42+
if (success) {
43+
router.replace('/(tabs)/home');
44+
} else {
45+
setError('Login failed. Please try again.');
46+
}
47+
} else if (result?.type === 'error') {
48+
setError('Authentication error. Please try again.');
49+
}
50+
} catch (err) {
51+
console.error('Google login error:', err);
52+
setError('An unexpected error occurred.');
53+
}
54+
};
55+
56+
const handleSkip = () => {
57+
// Guest mode - go to home without auth
58+
router.replace('/(tabs)/home');
59+
};
60+
61+
return (
62+
<SafeAreaView style={commonStyles.container}>
63+
<View style={styles.container}>
64+
{/* Logo Section */}
65+
<View style={styles.logoSection}>
66+
<View style={styles.logoContainer}>
67+
<Ionicons name="globe" size={64} color={colors.primary} />
68+
</View>
69+
<Text style={styles.title}>WorldGuessr</Text>
70+
<Text style={styles.subtitle}>
71+
Explore the world, one location at a time
72+
</Text>
73+
</View>
74+
75+
{/* Login Section */}
76+
<View style={styles.loginSection}>
77+
{error && (
78+
<View style={styles.errorContainer}>
79+
<Text style={styles.errorText}>{error}</Text>
80+
</View>
81+
)}
82+
83+
<Pressable
84+
style={({ pressed }) => [
85+
styles.googleButton,
86+
pressed && { opacity: 0.8 },
87+
!request && styles.buttonDisabled,
88+
]}
89+
onPress={handleGoogleLogin}
90+
disabled={!request || isLoading}
91+
>
92+
{isLoading ? (
93+
<ActivityIndicator color={colors.text} />
94+
) : (
95+
<>
96+
<Ionicons name="logo-google" size={20} color={colors.text} />
97+
<Text style={styles.googleButtonText}>Continue with Google</Text>
98+
</>
99+
)}
100+
</Pressable>
101+
102+
<View style={styles.divider}>
103+
<View style={styles.dividerLine} />
104+
<Text style={styles.dividerText}>or</Text>
105+
<View style={styles.dividerLine} />
106+
</View>
107+
108+
<Pressable
109+
style={({ pressed }) => [
110+
styles.skipButton,
111+
pressed && { opacity: 0.8 },
112+
]}
113+
onPress={handleSkip}
114+
>
115+
<Text style={styles.skipButtonText}>Continue as Guest</Text>
116+
</Pressable>
117+
118+
<Text style={styles.disclaimer}>
119+
By continuing, you agree to our Terms of Service and Privacy Policy
120+
</Text>
121+
</View>
122+
</View>
123+
</SafeAreaView>
124+
);
125+
}
126+
127+
const styles = StyleSheet.create({
128+
container: {
129+
flex: 1,
130+
justifyContent: 'space-between',
131+
padding: spacing['2xl'],
132+
},
133+
logoSection: {
134+
flex: 1,
135+
justifyContent: 'center',
136+
alignItems: 'center',
137+
},
138+
logoContainer: {
139+
width: 120,
140+
height: 120,
141+
borderRadius: 60,
142+
backgroundColor: 'rgba(36, 87, 52, 0.2)',
143+
justifyContent: 'center',
144+
alignItems: 'center',
145+
marginBottom: spacing['2xl'],
146+
},
147+
title: {
148+
fontSize: fontSizes['4xl'],
149+
fontWeight: 'bold',
150+
color: colors.text,
151+
marginBottom: spacing.sm,
152+
},
153+
subtitle: {
154+
fontSize: fontSizes.md,
155+
color: colors.textSecondary,
156+
textAlign: 'center',
157+
},
158+
loginSection: {
159+
paddingBottom: spacing['2xl'],
160+
},
161+
errorContainer: {
162+
backgroundColor: 'rgba(239, 68, 68, 0.2)',
163+
borderRadius: borderRadius.md,
164+
padding: spacing.md,
165+
marginBottom: spacing.lg,
166+
},
167+
errorText: {
168+
color: colors.error,
169+
fontSize: fontSizes.sm,
170+
textAlign: 'center',
171+
},
172+
googleButton: {
173+
flexDirection: 'row',
174+
alignItems: 'center',
175+
justifyContent: 'center',
176+
backgroundColor: colors.white,
177+
paddingVertical: spacing.lg,
178+
borderRadius: borderRadius.lg,
179+
gap: spacing.md,
180+
},
181+
buttonDisabled: {
182+
opacity: 0.5,
183+
},
184+
googleButtonText: {
185+
fontSize: fontSizes.md,
186+
fontWeight: '600',
187+
color: '#333',
188+
},
189+
divider: {
190+
flexDirection: 'row',
191+
alignItems: 'center',
192+
marginVertical: spacing['2xl'],
193+
},
194+
dividerLine: {
195+
flex: 1,
196+
height: 1,
197+
backgroundColor: colors.cardBorder,
198+
},
199+
dividerText: {
200+
color: colors.textMuted,
201+
paddingHorizontal: spacing.lg,
202+
fontSize: fontSizes.sm,
203+
},
204+
skipButton: {
205+
alignItems: 'center',
206+
justifyContent: 'center',
207+
paddingVertical: spacing.lg,
208+
borderRadius: borderRadius.lg,
209+
borderWidth: 1,
210+
borderColor: colors.cardBorder,
211+
},
212+
skipButtonText: {
213+
fontSize: fontSizes.md,
214+
fontWeight: '500',
215+
color: colors.textSecondary,
216+
},
217+
disclaimer: {
218+
fontSize: fontSizes.xs,
219+
color: colors.textMuted,
220+
textAlign: 'center',
221+
marginTop: spacing['2xl'],
222+
lineHeight: 18,
223+
},
224+
});

0 commit comments

Comments
 (0)