import { Dispatch, FC, SetStateAction } from 'react' import { useTranslation } from 'react-i18next' import { SocialButton } from '../SocialButton' import { useAuthGoogleControllerLogin } from '@/api/query/auth-social/auth-social' import { ENV, isExpoGo, isWeb } from '@/constants' import { useCallback, useEffect, useState } from '@/hooks' import { assignPushToken, setToken } from '@/services' import { isSignedInAtom, store } from '@/store' import { showErrorToast } from '@/utils' export type GoogleButtonProps = { isDisabled: boolean setIsDisabled: Dispatch> } let NativeGoogleButton: FC = () => null if (!isExpoGo && !isWeb) { // Conditionally import makes it work with expo go import('@react-native-google-signin/google-signin').then(({ GoogleSignin, statusCodes }) => { type GoogleSignInError = Error & { code: keyof typeof statusCodes } NativeGoogleButton = ({ isDisabled, setIsDisabled }) => { const { t } = useTranslation() const { mutate: signInByGoogle } = useAuthGoogleControllerLogin() const [isGoogleButtonDisabled, setIsGoogleButtonDisabled] = useState(false) const [isLoading, setIsLoading] = useState(false) useEffect(() => { // No extra configuration is needed, // but for the more customization check: // https://github.com/react-native-google-signin/google-signin#configureoptions GoogleSignin?.configure?.({ webClientId: ENV.WEB_CLIENT_ID, }) }, []) const verifyPlayServices = useCallback(async (): Promise => { setIsGoogleButtonDisabled(!(await GoogleSignin?.hasPlayServices?.())) }, []) useEffect(() => { verifyPlayServices() }, [verifyPlayServices]) const verifyToken = useCallback(async (): Promise => { const tokenResponse = await GoogleSignin?.getTokens?.() const { accessToken } = tokenResponse || {} signInByGoogle( { data: { accessToken, }, }, { onSuccess: async (response) => { const { user, ...token } = response if (token) { await setToken(token) } store.set(isSignedInAtom, true) // Send push token to backend await assignPushToken() }, } ) }, [signInByGoogle]) const signIn = useCallback(async (): Promise => { setIsLoading(true) setIsDisabled(true) try { await GoogleSignin?.signIn?.() await verifyToken() } catch (error) { // TODO: This could be extracted to external function with an additional handling of the error codes const typedError = error as GoogleSignInError if (typedError?.code) { switch (typedError.code) { case statusCodes?.SIGN_IN_CANCELLED: case statusCodes?.IN_PROGRESS: break case statusCodes?.PLAY_SERVICES_NOT_AVAILABLE: showErrorToast({ description: t('errors.play_services_not_available') }) break default: showErrorToast({ description: t('errors.something_went_wrong') }) break } return } showErrorToast({ description: t('errors.something_went_wrong') }) } finally { setIsDisabled(false) setIsLoading(false) } }, [setIsDisabled, t, verifyToken]) return ( ) } }) } export { NativeGoogleButton }