@umituz/react-native-auth 3.4.19 → 3.4.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.ts +5 -4
- package/src/presentation/components/AuthBottomSheet.tsx +20 -69
- package/src/presentation/components/AuthBottomSheetWrapper.tsx +5 -57
- package/src/presentation/hooks/useAuthBottomSheet.ts +106 -0
- package/src/presentation/hooks/useAuthBottomSheetWrapper.ts +70 -0
- package/src/presentation/hooks/useGoogleAuth.ts +4 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-auth",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.21",
|
|
4
4
|
"description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
package/src/index.ts
CHANGED
|
@@ -172,6 +172,9 @@ export type { UseGoogleAuthResult, GoogleAuthConfig as GoogleAuthHookConfig } fr
|
|
|
172
172
|
export { useAppleAuth } from './presentation/hooks/useAppleAuth';
|
|
173
173
|
export type { UseAppleAuthResult } from './presentation/hooks/useAppleAuth';
|
|
174
174
|
|
|
175
|
+
export { useAuthBottomSheet } from './presentation/hooks/useAuthBottomSheet';
|
|
176
|
+
export { useAuthBottomSheetWrapper } from './presentation/hooks/useAuthBottomSheetWrapper';
|
|
177
|
+
|
|
175
178
|
export type { UserProfile, UpdateProfileParams } from './domain/entities/UserProfile';
|
|
176
179
|
|
|
177
180
|
// Domain Utils - Anonymous Names
|
|
@@ -217,10 +220,8 @@ export type { PasswordMatchIndicatorProps } from './presentation/components/Pass
|
|
|
217
220
|
export { AuthBottomSheet } from './presentation/components/AuthBottomSheet';
|
|
218
221
|
export type { AuthBottomSheetProps } from './presentation/components/AuthBottomSheet';
|
|
219
222
|
export { AuthBottomSheetWrapper } from './presentation/components/AuthBottomSheetWrapper';
|
|
220
|
-
export type {
|
|
221
|
-
|
|
222
|
-
SocialAuthConfiguration,
|
|
223
|
-
} from './presentation/components/AuthBottomSheetWrapper';
|
|
223
|
+
export type { AuthBottomSheetWrapperProps } from './presentation/components/AuthBottomSheetWrapper';
|
|
224
|
+
export type { SocialAuthConfiguration } from './presentation/hooks/useAuthBottomSheetWrapper';
|
|
224
225
|
export { SocialLoginButtons } from './presentation/components/SocialLoginButtons';
|
|
225
226
|
export type { SocialLoginButtonsProps } from './presentation/components/SocialLoginButtons';
|
|
226
227
|
export { ProfileSection } from './presentation/components/ProfileSection';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Bottom sheet modal for authentication (Login/Register)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React
|
|
6
|
+
import React from "react";
|
|
7
7
|
import { View, TouchableOpacity, ScrollView } from "react-native";
|
|
8
8
|
import {
|
|
9
9
|
useAppDesignTokens,
|
|
@@ -11,11 +11,9 @@ import {
|
|
|
11
11
|
AtomicIcon,
|
|
12
12
|
AtomicKeyboardAvoidingView,
|
|
13
13
|
BottomSheetModal,
|
|
14
|
-
type BottomSheetModalRef,
|
|
15
14
|
} from "@umituz/react-native-design-system";
|
|
16
15
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
17
|
-
import {
|
|
18
|
-
import { useAuth } from "../hooks/useAuth";
|
|
16
|
+
import { useAuthBottomSheet } from "../hooks/useAuthBottomSheet";
|
|
19
17
|
import { LoginForm } from "./LoginForm";
|
|
20
18
|
import { RegisterForm } from "./RegisterForm";
|
|
21
19
|
import { SocialLoginButtons } from "./SocialLoginButtons";
|
|
@@ -46,67 +44,19 @@ export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
|
|
|
46
44
|
}) => {
|
|
47
45
|
const tokens = useAppDesignTokens();
|
|
48
46
|
const { t } = useLocalization();
|
|
49
|
-
const modalRef = useRef<BottomSheetModalRef>(null);
|
|
50
47
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}, [isVisible]);
|
|
65
|
-
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (isAuthenticated && !isAnonymous && isVisible) {
|
|
68
|
-
hideAuthModal();
|
|
69
|
-
executePendingCallback();
|
|
70
|
-
}
|
|
71
|
-
}, [isAuthenticated, isAnonymous, isVisible, hideAuthModal, executePendingCallback]);
|
|
72
|
-
|
|
73
|
-
const handleDismiss = useCallback(() => {
|
|
74
|
-
hideAuthModal();
|
|
75
|
-
clearPendingCallback();
|
|
76
|
-
}, [hideAuthModal, clearPendingCallback]);
|
|
77
|
-
|
|
78
|
-
const handleClose = useCallback(() => {
|
|
79
|
-
modalRef.current?.dismiss();
|
|
80
|
-
handleDismiss();
|
|
81
|
-
}, [handleDismiss]);
|
|
82
|
-
|
|
83
|
-
const handleNavigateToRegister = useCallback(() => {
|
|
84
|
-
setMode("register");
|
|
85
|
-
}, [setMode]);
|
|
86
|
-
|
|
87
|
-
const handleNavigateToLogin = useCallback(() => {
|
|
88
|
-
setMode("login");
|
|
89
|
-
}, [setMode]);
|
|
90
|
-
|
|
91
|
-
const handleGoogleSignIn = useCallback(async () => {
|
|
92
|
-
if (!onGoogleSignIn) return;
|
|
93
|
-
setGoogleLoading(true);
|
|
94
|
-
try {
|
|
95
|
-
await onGoogleSignIn();
|
|
96
|
-
} finally {
|
|
97
|
-
setGoogleLoading(false);
|
|
98
|
-
}
|
|
99
|
-
}, [onGoogleSignIn]);
|
|
100
|
-
|
|
101
|
-
const handleAppleSignIn = useCallback(async () => {
|
|
102
|
-
if (!onAppleSignIn) return;
|
|
103
|
-
setAppleLoading(true);
|
|
104
|
-
try {
|
|
105
|
-
await onAppleSignIn();
|
|
106
|
-
} finally {
|
|
107
|
-
setAppleLoading(false);
|
|
108
|
-
}
|
|
109
|
-
}, [onAppleSignIn]);
|
|
48
|
+
const {
|
|
49
|
+
modalRef,
|
|
50
|
+
googleLoading,
|
|
51
|
+
appleLoading,
|
|
52
|
+
mode,
|
|
53
|
+
handleDismiss,
|
|
54
|
+
handleClose,
|
|
55
|
+
handleNavigateToRegister,
|
|
56
|
+
handleNavigateToLogin,
|
|
57
|
+
handleGoogleSignIn,
|
|
58
|
+
handleAppleSignIn,
|
|
59
|
+
} = useAuthBottomSheet({ onGoogleSignIn, onAppleSignIn });
|
|
110
60
|
|
|
111
61
|
return (
|
|
112
62
|
<BottomSheetModal
|
|
@@ -118,11 +68,6 @@ export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
|
|
|
118
68
|
<AtomicKeyboardAvoidingView
|
|
119
69
|
style={{ flex: 1 }}
|
|
120
70
|
>
|
|
121
|
-
<ScrollView
|
|
122
|
-
contentContainerStyle={styles.scrollContent}
|
|
123
|
-
showsVerticalScrollIndicator={false}
|
|
124
|
-
keyboardShouldPersistTaps="handled"
|
|
125
|
-
>
|
|
126
71
|
<TouchableOpacity
|
|
127
72
|
style={styles.closeButton}
|
|
128
73
|
onPress={handleClose}
|
|
@@ -133,6 +78,12 @@ export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
|
|
|
133
78
|
<AtomicIcon name="close" size="md" color="secondary" />
|
|
134
79
|
</TouchableOpacity>
|
|
135
80
|
|
|
81
|
+
<ScrollView
|
|
82
|
+
contentContainerStyle={styles.scrollContent}
|
|
83
|
+
showsVerticalScrollIndicator={false}
|
|
84
|
+
keyboardShouldPersistTaps="handled"
|
|
85
|
+
>
|
|
86
|
+
|
|
136
87
|
<View style={styles.header}>
|
|
137
88
|
<AtomicText type="headlineLarge" color="primary" style={styles.title}>
|
|
138
89
|
{mode === "login" ? t("auth.signIn") : t("auth.createAccount")}
|
|
@@ -18,19 +18,9 @@
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import React
|
|
22
|
-
import { Platform } from "react-native";
|
|
21
|
+
import React from "react";
|
|
23
22
|
import { AuthBottomSheet } from "./AuthBottomSheet";
|
|
24
|
-
import {
|
|
25
|
-
import { useAppleAuth } from "../hooks/useAppleAuth";
|
|
26
|
-
import type { SocialAuthProvider } from "../../domain/value-objects/AuthConfig";
|
|
27
|
-
|
|
28
|
-
declare const __DEV__: boolean;
|
|
29
|
-
|
|
30
|
-
export interface SocialAuthConfiguration {
|
|
31
|
-
google?: GoogleAuthConfig;
|
|
32
|
-
apple?: { enabled: boolean };
|
|
33
|
-
}
|
|
23
|
+
import { useAuthBottomSheetWrapper, type SocialAuthConfiguration } from "../hooks/useAuthBottomSheetWrapper";
|
|
34
24
|
|
|
35
25
|
export interface AuthBottomSheetWrapperProps {
|
|
36
26
|
/** Terms of Service URL */
|
|
@@ -55,51 +45,9 @@ export const AuthBottomSheetWrapper: React.FC<AuthBottomSheetWrapperProps> = ({
|
|
|
55
45
|
onPrivacyPress,
|
|
56
46
|
socialConfig,
|
|
57
47
|
}) => {
|
|
58
|
-
const {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const providers = useMemo<SocialAuthProvider[]>(() => {
|
|
62
|
-
const result: SocialAuthProvider[] = [];
|
|
63
|
-
|
|
64
|
-
if (Platform.OS === "ios" && socialConfig?.apple?.enabled && appleAvailable) {
|
|
65
|
-
result.push("apple");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (googleConfigured) {
|
|
69
|
-
result.push("google");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (__DEV__) {
|
|
73
|
-
// eslint-disable-next-line no-console
|
|
74
|
-
console.log("[AuthBottomSheetWrapper] Enabled providers:", result);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return result;
|
|
78
|
-
}, [socialConfig?.apple?.enabled, appleAvailable, googleConfigured]);
|
|
79
|
-
|
|
80
|
-
const handleGoogleSignIn = useCallback(async () => {
|
|
81
|
-
if (__DEV__) {
|
|
82
|
-
// eslint-disable-next-line no-console
|
|
83
|
-
console.log("[AuthBottomSheetWrapper] Google sign-in requested");
|
|
84
|
-
}
|
|
85
|
-
const result = await signInWithGoogle();
|
|
86
|
-
if (__DEV__) {
|
|
87
|
-
// eslint-disable-next-line no-console
|
|
88
|
-
console.log("[AuthBottomSheetWrapper] Google result:", result);
|
|
89
|
-
}
|
|
90
|
-
}, [signInWithGoogle]);
|
|
91
|
-
|
|
92
|
-
const handleAppleSignIn = useCallback(async () => {
|
|
93
|
-
if (__DEV__) {
|
|
94
|
-
// eslint-disable-next-line no-console
|
|
95
|
-
console.log("[AuthBottomSheetWrapper] Apple sign-in requested");
|
|
96
|
-
}
|
|
97
|
-
const result = await signInWithApple();
|
|
98
|
-
if (__DEV__) {
|
|
99
|
-
// eslint-disable-next-line no-console
|
|
100
|
-
console.log("[AuthBottomSheetWrapper] Apple result:", result);
|
|
101
|
-
}
|
|
102
|
-
}, [signInWithApple]);
|
|
48
|
+
const { providers, handleGoogleSignIn, handleAppleSignIn } = useAuthBottomSheetWrapper({
|
|
49
|
+
socialConfig,
|
|
50
|
+
});
|
|
103
51
|
|
|
104
52
|
return (
|
|
105
53
|
<AuthBottomSheet
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import type { BottomSheetModalRef } from "@umituz/react-native-design-system";
|
|
3
|
+
import { useAuthModalStore } from "../stores/authModalStore";
|
|
4
|
+
import { useAuth } from "../hooks/useAuth";
|
|
5
|
+
|
|
6
|
+
interface UseAuthBottomSheetProps {
|
|
7
|
+
onGoogleSignIn?: () => Promise<void>;
|
|
8
|
+
onAppleSignIn?: () => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useAuthBottomSheet({ onGoogleSignIn, onAppleSignIn }: UseAuthBottomSheetProps) {
|
|
12
|
+
const modalRef = useRef<BottomSheetModalRef>(null);
|
|
13
|
+
const [googleLoading, setGoogleLoading] = useState(false);
|
|
14
|
+
const [appleLoading, setAppleLoading] = useState(false);
|
|
15
|
+
|
|
16
|
+
const { isVisible, mode, hideAuthModal, setMode, executePendingCallback, clearPendingCallback } =
|
|
17
|
+
useAuthModalStore();
|
|
18
|
+
const { isAuthenticated, isAnonymous } = useAuth();
|
|
19
|
+
|
|
20
|
+
// Handle visibility sync with modalRef
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (isVisible) {
|
|
23
|
+
modalRef.current?.present();
|
|
24
|
+
} else {
|
|
25
|
+
modalRef.current?.dismiss();
|
|
26
|
+
}
|
|
27
|
+
}, [isVisible]);
|
|
28
|
+
|
|
29
|
+
const handleDismiss = useCallback(() => {
|
|
30
|
+
hideAuthModal();
|
|
31
|
+
clearPendingCallback();
|
|
32
|
+
}, [hideAuthModal, clearPendingCallback]);
|
|
33
|
+
|
|
34
|
+
const handleClose = useCallback(() => {
|
|
35
|
+
modalRef.current?.dismiss();
|
|
36
|
+
handleDismiss();
|
|
37
|
+
}, [handleDismiss]);
|
|
38
|
+
|
|
39
|
+
const prevIsAuthenticatedRef = useRef(isAuthenticated);
|
|
40
|
+
const prevIsVisibleRef = useRef(isVisible);
|
|
41
|
+
const prevIsAnonymousRef = useRef(isAnonymous);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
// Determine if user just successfully authenticated (either A: were not authed at all, or B: were anonymous and now aren't)
|
|
45
|
+
const justAuthenticated = !prevIsAuthenticatedRef.current && isAuthenticated;
|
|
46
|
+
const justConvertedFromAnonymous = prevIsAnonymousRef.current && !isAnonymous && isAuthenticated;
|
|
47
|
+
|
|
48
|
+
if ((justAuthenticated || justConvertedFromAnonymous) && isVisible && !isAnonymous) {
|
|
49
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
50
|
+
// eslint-disable-next-line no-console
|
|
51
|
+
console.log("[AuthBottomSheet] Auto-closing due to successful authentication transition", {
|
|
52
|
+
justAuthenticated,
|
|
53
|
+
justConvertedFromAnonymous,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
handleClose();
|
|
57
|
+
executePendingCallback();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Update refs for next render
|
|
61
|
+
prevIsAuthenticatedRef.current = isAuthenticated;
|
|
62
|
+
prevIsVisibleRef.current = isVisible;
|
|
63
|
+
prevIsAnonymousRef.current = isAnonymous;
|
|
64
|
+
}, [isAuthenticated, isVisible, isAnonymous, executePendingCallback, handleClose]);
|
|
65
|
+
|
|
66
|
+
const handleNavigateToRegister = useCallback(() => {
|
|
67
|
+
setMode("register");
|
|
68
|
+
}, [setMode]);
|
|
69
|
+
|
|
70
|
+
const handleNavigateToLogin = useCallback(() => {
|
|
71
|
+
setMode("login");
|
|
72
|
+
}, [setMode]);
|
|
73
|
+
|
|
74
|
+
const handleGoogleSignIn = useCallback(async () => {
|
|
75
|
+
if (!onGoogleSignIn) return;
|
|
76
|
+
setGoogleLoading(true);
|
|
77
|
+
try {
|
|
78
|
+
await onGoogleSignIn();
|
|
79
|
+
} finally {
|
|
80
|
+
setGoogleLoading(false);
|
|
81
|
+
}
|
|
82
|
+
}, [onGoogleSignIn]);
|
|
83
|
+
|
|
84
|
+
const handleAppleSignIn = useCallback(async () => {
|
|
85
|
+
if (!onAppleSignIn) return;
|
|
86
|
+
setAppleLoading(true);
|
|
87
|
+
try {
|
|
88
|
+
await onAppleSignIn();
|
|
89
|
+
} finally {
|
|
90
|
+
setAppleLoading(false);
|
|
91
|
+
}
|
|
92
|
+
}, [onAppleSignIn]);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
modalRef,
|
|
96
|
+
googleLoading,
|
|
97
|
+
appleLoading,
|
|
98
|
+
mode,
|
|
99
|
+
handleDismiss,
|
|
100
|
+
handleClose,
|
|
101
|
+
handleNavigateToRegister,
|
|
102
|
+
handleNavigateToLogin,
|
|
103
|
+
handleGoogleSignIn,
|
|
104
|
+
handleAppleSignIn,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
|
+
import { useGoogleAuth, type GoogleAuthConfig } from "./useGoogleAuth";
|
|
4
|
+
import { useAppleAuth } from "./useAppleAuth";
|
|
5
|
+
import type { SocialAuthProvider } from "../../domain/value-objects/AuthConfig";
|
|
6
|
+
|
|
7
|
+
declare const __DEV__: boolean;
|
|
8
|
+
|
|
9
|
+
export interface SocialAuthConfiguration {
|
|
10
|
+
google?: GoogleAuthConfig;
|
|
11
|
+
apple?: { enabled: boolean };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface UseAuthBottomSheetWrapperProps {
|
|
15
|
+
socialConfig?: SocialAuthConfiguration;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function useAuthBottomSheetWrapper({ socialConfig }: UseAuthBottomSheetWrapperProps) {
|
|
19
|
+
const { signInWithGoogle, googleConfigured } = useGoogleAuth(socialConfig?.google);
|
|
20
|
+
const { signInWithApple, appleAvailable } = useAppleAuth();
|
|
21
|
+
|
|
22
|
+
const providers = useMemo<SocialAuthProvider[]>(() => {
|
|
23
|
+
const result: SocialAuthProvider[] = [];
|
|
24
|
+
|
|
25
|
+
if (Platform.OS === "ios" && socialConfig?.apple?.enabled && appleAvailable) {
|
|
26
|
+
result.push("apple");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (googleConfigured) {
|
|
30
|
+
result.push("google");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (__DEV__) {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.log("[useAuthBottomSheetWrapper] Enabled providers:", result);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result;
|
|
39
|
+
}, [socialConfig?.apple?.enabled, appleAvailable, googleConfigured]);
|
|
40
|
+
|
|
41
|
+
const handleGoogleSignIn = useCallback(async () => {
|
|
42
|
+
if (__DEV__) {
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.log("[useAuthBottomSheetWrapper] Google sign-in requested");
|
|
45
|
+
}
|
|
46
|
+
const result = await signInWithGoogle();
|
|
47
|
+
if (__DEV__) {
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
console.log("[useAuthBottomSheetWrapper] Google result:", result);
|
|
50
|
+
}
|
|
51
|
+
}, [signInWithGoogle]);
|
|
52
|
+
|
|
53
|
+
const handleAppleSignIn = useCallback(async () => {
|
|
54
|
+
if (__DEV__) {
|
|
55
|
+
// eslint-disable-next-line no-console
|
|
56
|
+
console.log("[useAuthBottomSheetWrapper] Apple sign-in requested");
|
|
57
|
+
}
|
|
58
|
+
const result = await signInWithApple();
|
|
59
|
+
if (__DEV__) {
|
|
60
|
+
// eslint-disable-next-line no-console
|
|
61
|
+
console.log("[useAuthBottomSheetWrapper] Apple result:", result);
|
|
62
|
+
}
|
|
63
|
+
}, [signInWithApple]);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
providers,
|
|
67
|
+
handleGoogleSignIn,
|
|
68
|
+
handleAppleSignIn,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -14,51 +14,10 @@ import {
|
|
|
14
14
|
type SocialAuthResult,
|
|
15
15
|
} from "@umituz/react-native-firebase";
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
iosClientId: string;
|
|
20
|
-
webClientId: string;
|
|
21
|
-
androidClientId: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface AuthSessionAuthentication {
|
|
25
|
-
idToken?: string;
|
|
26
|
-
accessToken?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface AuthSessionResult {
|
|
30
|
-
type: "success" | "cancel" | "dismiss" | "error" | "locked";
|
|
31
|
-
authentication?: AuthSessionAuthentication;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface AuthRequest {
|
|
35
|
-
promptAsync: () => Promise<AuthSessionResult>;
|
|
36
|
-
}
|
|
17
|
+
import * as Google from "expo-auth-session/providers/google";
|
|
18
|
+
import * as WebBrowser from "expo-web-browser";
|
|
37
19
|
|
|
38
|
-
|
|
39
|
-
AuthRequest | null,
|
|
40
|
-
AuthSessionResult | null,
|
|
41
|
-
() => Promise<AuthSessionResult>,
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
// Dynamic imports to handle optional dependencies
|
|
45
|
-
type GoogleModule = { useAuthRequest: (config: GoogleAuthRequestConfig) => UseAuthRequestReturn };
|
|
46
|
-
type WebBrowserModule = { maybeCompleteAuthSession: () => void };
|
|
47
|
-
|
|
48
|
-
let Google: GoogleModule | null = null;
|
|
49
|
-
let WebBrowser: WebBrowserModule | null = null;
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
53
|
-
Google = require("expo-auth-session/providers/google") as GoogleModule;
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
55
|
-
WebBrowser = require("expo-web-browser") as WebBrowserModule;
|
|
56
|
-
if (WebBrowser) {
|
|
57
|
-
WebBrowser.maybeCompleteAuthSession();
|
|
58
|
-
}
|
|
59
|
-
} catch {
|
|
60
|
-
// expo-auth-session not available - silent fallback
|
|
61
|
-
}
|
|
20
|
+
WebBrowser.maybeCompleteAuthSession();
|
|
62
21
|
|
|
63
22
|
export interface GoogleAuthConfig {
|
|
64
23
|
iosClientId?: string;
|
|
@@ -123,7 +82,7 @@ export function useGoogleAuth(config?: GoogleAuthConfig): UseGoogleAuthResult {
|
|
|
123
82
|
}, [googleResponse, signInWithGoogleToken]);
|
|
124
83
|
|
|
125
84
|
const signInWithGoogle = useCallback(async (): Promise<SocialAuthResult> => {
|
|
126
|
-
if (!
|
|
85
|
+
if (!promptGoogleAsync) {
|
|
127
86
|
return { success: false, error: "expo-auth-session is not available" };
|
|
128
87
|
}
|
|
129
88
|
|