import { Platform } from 'react-native' import type { AddScopesParams, ConfigureParams, HasPlayServicesParams, SignInParams, User, } from '../../types' import { PortalGoogleSignInModule, isTurboModuleEnabled } from '../NativeModule' import { Spec as NativePortalGoogleSignIn } from '../NativePortalGoogleSignIn' const PortalGoogleSignIn = PortalGoogleSignInModule as NativePortalGoogleSignIn const IS_IOS = Platform.OS === 'ios' class GoogleSignIn { configPromise?: Promise user: User | null = null constructor() { if (!PortalGoogleSignIn) { console.error( `PortalGoogleSignIn native module is not correctly linked. Please read the readme, setup and troubleshooting instructions carefully or try manual linking.`, ) } } async signIn(options: SignInParams = {}): Promise { await this.configPromise return (await PortalGoogleSignIn.signIn(options)) as unknown as User } hasPlayServices( options: HasPlayServicesParams = { showPlayServicesUpdateDialog: true }, ): Promise { if (IS_IOS) { return new Promise((resolve) => resolve(true)) } else { if (options && options.showPlayServicesUpdateDialog === undefined) { throw new Error( 'PortalGoogleSignIn: Missing property `showPlayServicesUpdateDialog` in options object for `hasPlayServices`', ) } return PortalGoogleSignIn.playServicesAvailable( options.showPlayServicesUpdateDialog!, ) } } configure(options: ConfigureParams = {}): void { if (options.offlineAccess && !options.webClientId) { throw new Error( 'PortalGoogleSignIn: offline use requires server web ClientID', ) } this.configPromise = PortalGoogleSignIn.configure(options).then(() => {}) } async addScopes(options: AddScopesParams): Promise { const isSignedIn = await this.isSignedIn() if (!isSignedIn) { return null } return (await (IS_IOS ? PortalGoogleSignIn.addScopes({ scopes: options.scopes || [] }) : PortalGoogleSignIn.getCurrentUser())) as unknown as User } async signInSilently(): Promise { await this.configPromise return PortalGoogleSignIn.signInSilently() as unknown as User } async signOut(): Promise { this.user = null return await PortalGoogleSignIn.signOut() } async revokeAccess(): Promise { this.user = null return await PortalGoogleSignIn.revokeAccess() } async isSignedIn(): Promise { const isSignedIn = await PortalGoogleSignIn.isSignedIn() if (isSignedIn) { this.user = await this.getCurrentUser() } return isSignedIn } async getCurrentUser(): Promise { if (this.user) { return this.user } return (await PortalGoogleSignIn.getCurrentUser()) as unknown as User | null } async clearCachedAccessToken(tokenString: string): Promise { if (!tokenString || typeof tokenString !== 'string') { return Promise.reject( 'GoogleSignIn: clearCachedAccessToken() expects a string token.', ) } return IS_IOS ? Promise.resolve(null) : PortalGoogleSignIn.clearCachedAccessToken(tokenString) } async getTokens(): Promise<{ idToken: string; accessToken: string }> { if (IS_IOS) { const tokens = await PortalGoogleSignIn.getTokens() return tokens } else { const userObject = await PortalGoogleSignIn.getTokens() return { idToken: userObject.idToken, accessToken: userObject.accessToken, } } } } export default new GoogleSignIn() // On TurboModule (new arch), constants are retrieved via getConstants() method // On old architecture, constants are exposed as static properties on the module const constants = isTurboModuleEnabled ? PortalGoogleSignIn.getConstants() : (PortalGoogleSignIn as unknown as { SIGN_IN_CANCELLED: string IN_PROGRESS: string PLAY_SERVICES_NOT_AVAILABLE: string SIGN_IN_REQUIRED: string }) export const statusCodes = { SIGN_IN_CANCELLED: constants.SIGN_IN_CANCELLED, IN_PROGRESS: constants.IN_PROGRESS, PLAY_SERVICES_NOT_AVAILABLE: constants.PLAY_SERVICES_NOT_AVAILABLE, SIGN_IN_REQUIRED: constants.SIGN_IN_REQUIRED, } as const