import { ResponseType } from "expo-auth-session"; import * as Google from "expo-auth-session/providers/google"; import Constants from "expo-constants"; import * as WebBrowser from "expo-web-browser"; import { useEffect, useMemo, useState } from "react"; import { useAuth } from "./auth"; import { t } from "./locales"; WebBrowser.maybeCompleteAuthSession(); type GoogleClientIds = { iosClientId?: string; androidClientId?: string; webClientId?: string; }; function getGoogleClientIds(): GoogleClientIds { const env = (process as any)?.env || {}; const extra = (Constants.manifest as any)?.extra || (Constants.expoConfig as any)?.extra || {}; return { iosClientId: env.EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID || extra.GOOGLE_IOS_CLIENT_ID, androidClientId: env.EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID || extra.GOOGLE_ANDROID_CLIENT_ID, webClientId: env.EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID || extra.GOOGLE_WEB_CLIENT_ID || env.EXPO_PUBLIC_GOOGLE_EXPO_CLIENT_ID || extra.GOOGLE_EXPO_CLIENT_ID, }; } export function useGoogleAuth() { const { signInWithGoogle } = useAuth(); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(""); const clientIds = useMemo(() => getGoogleClientIds(), []); const [request, response, promptAsync] = Google.useAuthRequest({ iosClientId: clientIds.iosClientId, androidClientId: clientIds.androidClientId, webClientId: clientIds.webClientId, responseType: ResponseType.IdToken, scopes: ["openid", "profile", "email"], selectAccount: true, }); useEffect(() => { const run = async () => { if (!response) return; if (response.type === "success") { const idToken = response.params?.id_token || response.authentication?.idToken; if (!idToken) { setError(t("googleMissingIdToken")); setIsLoading(false); return; } const result = await signInWithGoogle(idToken); if (!result.success) { setError(result.reason || t("googleSignInError")); } setIsLoading(false); return; } if (response.type === "error") { setError(response.error?.message || t("googleSignInError")); } // On cancel/dismissed/locked, just reset loading and keep the current screen state. setIsLoading(false); }; run().catch(() => { setError(t("googleSignInError")); setIsLoading(false); }); }, [response, signInWithGoogle]); const continueWithGoogle = async () => { setError(""); if (!request) { setError(t("googleConfigMissing")); return; } setIsLoading(true); try { const result = await promptAsync(); if (result.type === "cancel" || result.type === "dismiss") { setIsLoading(false); } } catch { setError(t("googleSignInError")); setIsLoading(false); } }; return { continueWithGoogle, isLoading, error, }; }