import React from "react"; import * as AppleAuthentication from "expo-apple-authentication"; import { StyleSheet, Alert } from "react-native"; import { ThemedView } from "@/components/theme/Theme"; import { useColorScheme } from "@/hooks/useColorScheme"; import * as Notifications from "expo-notifications"; import Constants from "expo-constants"; import { saveUser, saveInitialData } from "@/components/services/SecureStore"; import type { InitialData, User } from "@/constants/Types"; const SignInScreen({onSignIn}: {onSignIn: () => void}) => { const scheme = useColorScheme() ?? 'dark'; const handleAppleSignIn = async () => { try { const credential = await AppleAuthentication.signInAsync({ requestedScopes: [ AppleAuthentication.AppleAuthenticationScope.EMAIL, AppleAuthentication.AppleAuthenticationScope.FULL_NAME, ], }); const projectId = Constants.expoConfig?.extra?.eas?.projectId; if (!projectId) throw new Error('Project ID not found in eas.json'); const pushToken = await Notifications.getExpoPushTokenAsync({ projectId: projectId, }); console.log( credential.user, credential.email, credential.fullName?.givenName, credential.fullName?.familyName, pushToken ); const initialData = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/users/getUserByAppleId` + `?appleId=${credential.user}`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '', }, }); console.log(initialData); if (initialData.status === 404 || !initialData.ok) { if (!credential.user || !credential.email || !credential.fullName?.givenName || !credential.fullName?.familyName || !pushToken || credential.email.length === 0) { Alert.alert( 'Sign in error', 'Unable to create an account. ' + 'Remove App from Sign in with Apple & try again.', ); throw new Error( 'Incomplete user data. This shouldn\'t happen & means that user has ' + 'previously signed in with Apple, but their user data did not ' + 'save in the database.' ); } const userResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/users/createUser`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '', }, body: JSON.stringify({ appleId: credential.user, email: credential.email, fullName: `${credential.fullName?.givenName} ${credential.fullName?.familyName}`, pushToken: pushToken, }), }); if (!userResponse.ok) { const errorBody = await userResponse.text(); console.error( 'API error: No user returned: ', userResponse.status, errorBody ); throw new Error(`Failed to create user: ${userResponse.status} ${errorBody}`); } const user: User = await userResponse.json() as User; await saveUser(user); } else if (initialData.ok) { const allData: InitialData = await initialData.json() as InitialData; console.log('Existing user found! Saving data...'); if (allData.user.pushToken !== pushToken.data) { const updatePushTokenResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/users/updatePushToken`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '', }, body: JSON.stringify({ userId: allData.user.id, pushToken: pushToken.data, }), }); if (!updatePushTokenResponse.ok) { throw new Error( `Failed to update push token: ${updatePushTokenResponse.status}` ); } } else { console.log('Push token is up to date.'); } allData.user.pushToken = pushToken.data; await saveInitialData(allData); } onSignIn(); } catch (error) { console.error('Error signing in:', error); if (error.code === 'ERR_REQUEST_CANCELLED') { Alert.alert('Sign in error', 'Sign in was cancelled.'); } else { Alert.alert( 'Sign in error', 'An error occurred while signing in. Please try again or contact support.' ); } } }; return ( ); }; export default SignInScreen; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, button: { width: 200, height: 45, }, });