@chem-po/firebase-native 0.0.39 → 0.0.41
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/lib/commonjs/components/FirebaseSignIn.js +20 -14
- package/lib/commonjs/components/FirebaseSignIn.js.map +1 -1
- package/lib/commonjs/components/PhoneVerify.js +45 -33
- package/lib/commonjs/components/PhoneVerify.js.map +1 -1
- package/lib/commonjs/components/TwoFactorAuthModal.js +71 -15
- package/lib/commonjs/components/TwoFactorAuthModal.js.map +1 -1
- package/lib/commonjs/hooks/usePhoneVerify.js +13 -5
- package/lib/commonjs/hooks/usePhoneVerify.js.map +1 -1
- package/lib/module/components/FirebaseSignIn.js +21 -15
- package/lib/module/components/FirebaseSignIn.js.map +1 -1
- package/lib/module/components/PhoneVerify.js +47 -35
- package/lib/module/components/PhoneVerify.js.map +1 -1
- package/lib/module/components/TwoFactorAuthModal.js +71 -16
- package/lib/module/components/TwoFactorAuthModal.js.map +1 -1
- package/lib/module/hooks/usePhoneVerify.js +13 -5
- package/lib/module/hooks/usePhoneVerify.js.map +1 -1
- package/lib/typescript/components/FirebaseSignIn.d.ts.map +1 -1
- package/lib/typescript/components/PhoneVerify.d.ts.map +1 -1
- package/lib/typescript/components/TwoFactorAuthModal.d.ts +1 -0
- package/lib/typescript/components/TwoFactorAuthModal.d.ts.map +1 -1
- package/lib/typescript/hooks/usePhoneVerify.d.ts +3 -1
- package/lib/typescript/hooks/usePhoneVerify.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/components/FirebaseSignIn.tsx +21 -14
- package/src/components/PhoneVerify.tsx +46 -33
- package/src/components/TwoFactorAuthModal.tsx +87 -24
- package/src/hooks/usePhoneVerify.ts +15 -4
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@chem-po/firebase-native",
|
|
3
3
|
"author": "Elan Canfield",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.41",
|
|
6
6
|
"main": "lib/commonjs/index.js",
|
|
7
7
|
"types": "lib/typescript/index.d.ts",
|
|
8
8
|
"source": "src/index.ts",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"react-native-paper": "^5.14.3",
|
|
45
45
|
"react-native-svg": "15.11.2",
|
|
46
46
|
"zustand": "^4.3.3",
|
|
47
|
-
"@chem-po/
|
|
48
|
-
"@chem-po/react-native": "0.0.
|
|
49
|
-
"@chem-po/
|
|
47
|
+
"@chem-po/core": "0.0.41",
|
|
48
|
+
"@chem-po/react-native": "0.0.41",
|
|
49
|
+
"@chem-po/react": "0.0.41"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@babel/core": "^7.26.0",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useBackend } from '../hooks'
|
|
2
2
|
|
|
3
3
|
import { AppleAuthProvider, GoogleAuthProvider, ThirdPartyAuthProvider } from '@chem-po/core'
|
|
4
|
-
import { TextField, useBorderColor, useToast } from '@chem-po/react'
|
|
4
|
+
import { TextField, useBorderColor, useTextColor, useToast } from '@chem-po/react'
|
|
5
5
|
import { LoadingButton, StandaloneInput, Txt } from '@chem-po/react-native'
|
|
6
|
+
import { ButtonText } from '@chem-po/react-native/src/components/button/ButtonText'
|
|
6
7
|
import appleAuth from '@invertase/react-native-apple-authentication'
|
|
7
8
|
import React, { useCallback, useState } from 'react'
|
|
8
9
|
import { StyleSheet, View } from 'react-native'
|
|
@@ -40,14 +41,19 @@ const ThirdPartyLogin = ({ provider }: { provider: GoogleAuthProvider | AppleAut
|
|
|
40
41
|
})
|
|
41
42
|
}, [auth, provider, showError])
|
|
42
43
|
|
|
43
|
-
const
|
|
44
|
-
|
|
44
|
+
const textColor = useTextColor(400)
|
|
45
45
|
return (
|
|
46
46
|
<View style={styles.row}>
|
|
47
|
-
<LoadingButton
|
|
47
|
+
<LoadingButton
|
|
48
|
+
color={textColor}
|
|
49
|
+
variant="outline"
|
|
50
|
+
style={[styles.googleLoginButton]}
|
|
51
|
+
onPress={handleSignIn}>
|
|
48
52
|
<View style={styles.googleLogin}>
|
|
49
53
|
{thirdPartyInfo[provider.name].icon}
|
|
50
|
-
<
|
|
54
|
+
<ButtonText
|
|
55
|
+
variant="outline"
|
|
56
|
+
color={textColor}>{`Log In with ${thirdPartyInfo[provider.name].name}`}</ButtonText>
|
|
51
57
|
</View>
|
|
52
58
|
</LoadingButton>
|
|
53
59
|
</View>
|
|
@@ -57,20 +63,18 @@ const ThirdPartyLogin = ({ provider }: { provider: GoogleAuthProvider | AppleAut
|
|
|
57
63
|
const EmailPasswordLogin = () => {
|
|
58
64
|
const [email, setEmail] = useState('')
|
|
59
65
|
const [password, setPassword] = useState('')
|
|
60
|
-
const [isLoading, setIsLoading] = useState(false)
|
|
61
66
|
const [error, setError] = useState<string | null>(null)
|
|
67
|
+
const forgotPasswordTextColor = useTextColor(400)
|
|
62
68
|
|
|
63
69
|
const { auth } = useBackend()
|
|
64
70
|
const { showInfo } = useToast()
|
|
65
71
|
|
|
66
72
|
const handleLogin = async () => {
|
|
67
|
-
setIsLoading(true)
|
|
68
73
|
try {
|
|
69
74
|
await auth.loginWithPassword({ name: 'email' }, { email, password })
|
|
70
75
|
} catch (error) {
|
|
71
76
|
setError(error instanceof Error ? error.message : 'An unknown error occurred')
|
|
72
77
|
}
|
|
73
|
-
setIsLoading(false)
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
return (
|
|
@@ -85,18 +89,19 @@ const EmailPasswordLogin = () => {
|
|
|
85
89
|
<View style={styles.row}>
|
|
86
90
|
<View style={styles.forgotPassword}>
|
|
87
91
|
<LoadingButton
|
|
92
|
+
color={forgotPasswordTextColor}
|
|
88
93
|
textStyle={styles.forgotPasswordButtonText}
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
style={styles.forgotPasswordButton}
|
|
95
|
+
size="sm"
|
|
96
|
+
variant="outline"
|
|
97
|
+
onPress={async () => {
|
|
91
98
|
// console.log('press')
|
|
92
99
|
showInfo('Visit our website to reset your password')
|
|
93
100
|
}}>
|
|
94
101
|
Forgot Password?
|
|
95
102
|
</LoadingButton>
|
|
96
103
|
</View>
|
|
97
|
-
<LoadingButton onPress={() => handleLogin()}
|
|
98
|
-
Sign In
|
|
99
|
-
</LoadingButton>
|
|
104
|
+
<LoadingButton onPress={() => handleLogin()}>Sign In</LoadingButton>
|
|
100
105
|
</View>
|
|
101
106
|
</View>
|
|
102
107
|
)
|
|
@@ -149,7 +154,7 @@ const styles = StyleSheet.create({
|
|
|
149
154
|
},
|
|
150
155
|
column: {
|
|
151
156
|
flexDirection: 'column',
|
|
152
|
-
gap:
|
|
157
|
+
gap: 10,
|
|
153
158
|
flex: 1,
|
|
154
159
|
width: '100%',
|
|
155
160
|
alignItems: 'center',
|
|
@@ -176,6 +181,7 @@ const styles = StyleSheet.create({
|
|
|
176
181
|
},
|
|
177
182
|
forgotPasswordButton: {
|
|
178
183
|
borderWidth: 0,
|
|
184
|
+
backgroundColor: 'transparent',
|
|
179
185
|
},
|
|
180
186
|
forgotPasswordButtonText: {
|
|
181
187
|
fontSize: 14,
|
|
@@ -183,6 +189,7 @@ const styles = StyleSheet.create({
|
|
|
183
189
|
row: {
|
|
184
190
|
flexDirection: 'row',
|
|
185
191
|
justifyContent: 'space-between',
|
|
192
|
+
alignItems: 'center',
|
|
186
193
|
width: '100%',
|
|
187
194
|
},
|
|
188
195
|
forgotPassword: {
|
|
@@ -1,53 +1,66 @@
|
|
|
1
|
-
import { PhoneEnrollmentFactor } from '@chem-po/core'
|
|
2
|
-
import { useAuth } from '@chem-po/react'
|
|
3
|
-
import { Txt } from '@chem-po/react-native'
|
|
4
|
-
import React from 'react'
|
|
5
|
-
import {
|
|
1
|
+
import { formatPhoneNumber, PhoneEnrollmentFactor } from '@chem-po/core'
|
|
2
|
+
import { useAuth, useBorderColor, useButtonColor, usePlaceholderColor, useTextColor } from '@chem-po/react'
|
|
3
|
+
import { CircularProgress, LoadingButton, Txt } from '@chem-po/react-native'
|
|
4
|
+
import React, { useMemo } from 'react'
|
|
5
|
+
import { StyleSheet, TextInput, View } from 'react-native'
|
|
6
6
|
import { usePhoneVerify } from '../hooks/usePhoneVerify'
|
|
7
7
|
|
|
8
8
|
// UI to send code and verify code
|
|
9
9
|
export const PhoneVerify = ({ factor }: { factor: PhoneEnrollmentFactor }) => {
|
|
10
|
-
const { handleVerify, verifying, error, code, setCode } =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
10
|
+
const { handleVerify, verifying, error, code, setCode, sendCode, sendingCode } = usePhoneVerify(factor, true)
|
|
11
|
+
const { multiFactorVerification: twoFactorVerification, multiFactorLoading: loading } = useAuth()
|
|
12
|
+
const buttonBackgroundColor = useButtonColor()
|
|
13
|
+
const borderColor = useBorderColor()
|
|
14
|
+
const textColor = useTextColor()
|
|
15
|
+
const placeholderColor = usePlaceholderColor()
|
|
14
16
|
|
|
15
17
|
const verificationId = twoFactorVerification?.verificationId
|
|
18
|
+
const formattedPhoneNumber = useMemo(
|
|
19
|
+
() =>
|
|
20
|
+
Number.isNaN(Number(factor.phoneNumber))
|
|
21
|
+
? factor.phoneNumber
|
|
22
|
+
: formatPhoneNumber(factor.phoneNumber),
|
|
23
|
+
[factor.phoneNumber]
|
|
24
|
+
)
|
|
16
25
|
|
|
17
26
|
let body: React.ReactNode = null
|
|
18
27
|
|
|
19
|
-
if (
|
|
28
|
+
if (sendingCode) {
|
|
20
29
|
body = (
|
|
21
30
|
<View style={styles.container}>
|
|
22
|
-
<
|
|
31
|
+
<CircularProgress size='large' />
|
|
23
32
|
<Txt style={styles.text}>Sending verification code...</Txt>
|
|
24
33
|
</View>
|
|
25
34
|
)
|
|
26
|
-
} else if (verificationId) {
|
|
35
|
+
} else if (verificationId || verifying) {
|
|
27
36
|
body = (
|
|
28
37
|
<View style={styles.container}>
|
|
29
38
|
<Txt style={styles.text}>Enter the code sent to your phone:</Txt>
|
|
30
39
|
<TextInput
|
|
31
|
-
style={styles.input}
|
|
40
|
+
style={[styles.input, { borderColor, color: textColor }]}
|
|
32
41
|
value={code}
|
|
42
|
+
placeholderTextColor={placeholderColor}
|
|
33
43
|
onChangeText={setCode}
|
|
34
|
-
placeholder=
|
|
35
|
-
keyboardType=
|
|
44
|
+
placeholder='Verification Code'
|
|
45
|
+
keyboardType='number-pad'
|
|
36
46
|
maxLength={6}
|
|
37
47
|
/>
|
|
38
48
|
{error ? <Txt style={styles.errorText}>{error}</Txt> : null}
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
</
|
|
49
|
+
<LoadingButton variant='solid' onPress={handleVerify} color={buttonBackgroundColor}>
|
|
50
|
+
Verify
|
|
51
|
+
</LoadingButton>
|
|
42
52
|
</View>
|
|
43
53
|
)
|
|
44
54
|
} else {
|
|
45
55
|
body = (
|
|
46
56
|
<View style={styles.container}>
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
<Txt style={styles.
|
|
50
|
-
</
|
|
57
|
+
<View style={styles.textContainer}>
|
|
58
|
+
<Txt style={styles.infoText}>We'll send a verification code to:</Txt>
|
|
59
|
+
<Txt style={styles.text}>{formattedPhoneNumber}</Txt>
|
|
60
|
+
</View>
|
|
61
|
+
<LoadingButton variant='solid' onPress={sendCode} disabled={loading} color={buttonBackgroundColor}>
|
|
62
|
+
Send Verification Code
|
|
63
|
+
</LoadingButton>
|
|
51
64
|
</View>
|
|
52
65
|
)
|
|
53
66
|
}
|
|
@@ -64,7 +77,17 @@ const styles = StyleSheet.create({
|
|
|
64
77
|
flex: 1,
|
|
65
78
|
alignItems: 'center',
|
|
66
79
|
justifyContent: 'center',
|
|
67
|
-
gap:
|
|
80
|
+
gap: 8,
|
|
81
|
+
},
|
|
82
|
+
textContainer: {
|
|
83
|
+
alignItems: 'center',
|
|
84
|
+
justifyContent: 'center',
|
|
85
|
+
gap: 4,
|
|
86
|
+
},
|
|
87
|
+
infoText: {
|
|
88
|
+
fontSize: 15,
|
|
89
|
+
opacity: 0.8,
|
|
90
|
+
textAlign: 'center',
|
|
68
91
|
},
|
|
69
92
|
text: {
|
|
70
93
|
fontSize: 16,
|
|
@@ -75,22 +98,12 @@ const styles = StyleSheet.create({
|
|
|
75
98
|
width: '100%',
|
|
76
99
|
height: 48,
|
|
77
100
|
borderWidth: 1,
|
|
78
|
-
borderColor: '#ccc',
|
|
79
101
|
borderRadius: 8,
|
|
80
102
|
paddingHorizontal: 16,
|
|
81
103
|
fontSize: 16,
|
|
82
104
|
marginBottom: 8,
|
|
83
105
|
},
|
|
84
|
-
button: {
|
|
85
|
-
backgroundColor: '#007AFF',
|
|
86
|
-
paddingHorizontal: 24,
|
|
87
|
-
paddingVertical: 12,
|
|
88
|
-
borderRadius: 8,
|
|
89
|
-
minWidth: 200,
|
|
90
|
-
alignItems: 'center',
|
|
91
|
-
},
|
|
92
106
|
buttonText: {
|
|
93
|
-
color: 'white',
|
|
94
107
|
fontSize: 16,
|
|
95
108
|
fontWeight: '600',
|
|
96
109
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EnrollmentFactor, PhoneEnrollmentFactor } from '@chem-po/core'
|
|
2
|
-
import { useAuth, useBackgroundColor } from '@chem-po/react'
|
|
3
|
-
import { Txt } from '@chem-po/react-native'
|
|
2
|
+
import { useAuth, useBackgroundColor, useBorderColor, useIconColor } from '@chem-po/react'
|
|
3
|
+
import { Txt, useFont } from '@chem-po/react-native'
|
|
4
|
+
import { Ionicons } from '@expo/vector-icons'
|
|
4
5
|
import React, { useState } from 'react'
|
|
5
6
|
import { ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native'
|
|
6
7
|
import { Modal, Portal } from 'react-native-paper'
|
|
@@ -8,6 +9,46 @@ import { useBackend } from '../hooks/backend'
|
|
|
8
9
|
import { AuthenticatorVerify } from './AuthenticatorVerify'
|
|
9
10
|
import { PhoneVerify } from './PhoneVerify'
|
|
10
11
|
|
|
12
|
+
const FactorView = ({
|
|
13
|
+
factor,
|
|
14
|
+
buttonBackgroundColor,
|
|
15
|
+
iconColor,
|
|
16
|
+
borderColor,
|
|
17
|
+
onPress,
|
|
18
|
+
}: {
|
|
19
|
+
factor: EnrollmentFactor
|
|
20
|
+
buttonBackgroundColor: string
|
|
21
|
+
iconColor: string
|
|
22
|
+
borderColor: string
|
|
23
|
+
onPress: () => void
|
|
24
|
+
}) => {
|
|
25
|
+
return (
|
|
26
|
+
<TouchableOpacity
|
|
27
|
+
style={[
|
|
28
|
+
styles.factorButton,
|
|
29
|
+
{
|
|
30
|
+
backgroundColor: buttonBackgroundColor,
|
|
31
|
+
borderColor,
|
|
32
|
+
},
|
|
33
|
+
]}
|
|
34
|
+
onPress={onPress}
|
|
35
|
+
>
|
|
36
|
+
<View style={styles.factorContent}>
|
|
37
|
+
<Ionicons
|
|
38
|
+
name={factor.type === 'phone' ? 'phone-portrait' : 'qr-code'}
|
|
39
|
+
size={20}
|
|
40
|
+
color={iconColor}
|
|
41
|
+
/>
|
|
42
|
+
<Txt style={styles.factorHeaderText}>
|
|
43
|
+
{factor.type === 'phone' ? `Phone: ${factor.phoneNumber}` : 'Authenticator App'}
|
|
44
|
+
</Txt>
|
|
45
|
+
{factor.displayName ? (
|
|
46
|
+
<Txt style={styles.factorDetailsText}>{factor.displayName}</Txt>
|
|
47
|
+
) : null}
|
|
48
|
+
</View>
|
|
49
|
+
</TouchableOpacity>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
11
52
|
|
|
12
53
|
const TwoFactorSelect = ({
|
|
13
54
|
factors,
|
|
@@ -17,30 +58,22 @@ const TwoFactorSelect = ({
|
|
|
17
58
|
onSelect: (factor: EnrollmentFactor) => void
|
|
18
59
|
}) => {
|
|
19
60
|
const buttonBackgroundColor = useBackgroundColor(100)
|
|
61
|
+
const borderColor = useBorderColor()
|
|
62
|
+
const iconColor = useIconColor()
|
|
63
|
+
const textFont = useFont('body', 'md')
|
|
20
64
|
return (
|
|
21
65
|
<View style={styles.selectContainer}>
|
|
22
|
-
<Txt style={styles.selectTitle}>Select an option to verify with:</Txt>
|
|
66
|
+
<Txt style={[styles.selectTitle, textFont]}>Select an option to verify with:</Txt>
|
|
23
67
|
<View style={styles.factorsList}>
|
|
24
68
|
{factors.map((factor) => (
|
|
25
|
-
<
|
|
26
|
-
key={factor.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
backgroundColor: buttonBackgroundColor,
|
|
31
|
-
},
|
|
32
|
-
]}
|
|
69
|
+
<FactorView
|
|
70
|
+
key={`${factor.type}-${factor.enrollmentTime}`}
|
|
71
|
+
factor={factor}
|
|
72
|
+
buttonBackgroundColor={buttonBackgroundColor}
|
|
33
73
|
onPress={() => onSelect(factor)}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</Txt>
|
|
38
|
-
{
|
|
39
|
-
factor.displayName ? (
|
|
40
|
-
<Txt style={styles.factorDetailsText}>{factor.displayName}</Txt>
|
|
41
|
-
) : null
|
|
42
|
-
}
|
|
43
|
-
</TouchableOpacity>
|
|
74
|
+
iconColor={iconColor}
|
|
75
|
+
borderColor={borderColor}
|
|
76
|
+
/>
|
|
44
77
|
))}
|
|
45
78
|
</View>
|
|
46
79
|
</View>
|
|
@@ -83,7 +116,9 @@ export const TwoFactorAuthModal = () => {
|
|
|
83
116
|
<Portal>
|
|
84
117
|
<Modal
|
|
85
118
|
visible={true}
|
|
86
|
-
onDismiss={() => {
|
|
119
|
+
onDismiss={() => {
|
|
120
|
+
auth.logout()
|
|
121
|
+
}}
|
|
87
122
|
style={styles.modal}
|
|
88
123
|
>
|
|
89
124
|
<View style={[styles.modalContent, { backgroundColor }]}>
|
|
@@ -96,6 +131,28 @@ export const TwoFactorAuthModal = () => {
|
|
|
96
131
|
)
|
|
97
132
|
}
|
|
98
133
|
|
|
134
|
+
const testFactor: EnrollmentFactor = {
|
|
135
|
+
uid: 'test',
|
|
136
|
+
type: 'phone',
|
|
137
|
+
phoneNumber: '1234567890',
|
|
138
|
+
displayName: 'Test Phone',
|
|
139
|
+
enrollmentTime: '2021-01-01',
|
|
140
|
+
}
|
|
141
|
+
export const TestTwoFactorVerifyModal = () => {
|
|
142
|
+
const backgroundColor = useBackgroundColor(150)
|
|
143
|
+
return (
|
|
144
|
+
<Portal>
|
|
145
|
+
<Modal visible={true} onDismiss={() => {}} style={styles.modal}>
|
|
146
|
+
<View style={[styles.modalContent, { backgroundColor }]}>
|
|
147
|
+
<ScrollView contentContainerStyle={styles.scrollContent}>
|
|
148
|
+
<TwoFactorVerify factorInfo={testFactor} />
|
|
149
|
+
</ScrollView>
|
|
150
|
+
</View>
|
|
151
|
+
</Modal>
|
|
152
|
+
</Portal>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
99
156
|
const styles = StyleSheet.create({
|
|
100
157
|
modal: {
|
|
101
158
|
margin: 0,
|
|
@@ -113,18 +170,24 @@ const styles = StyleSheet.create({
|
|
|
113
170
|
},
|
|
114
171
|
selectTitle: {
|
|
115
172
|
fontSize: 16,
|
|
116
|
-
marginBottom:
|
|
173
|
+
marginBottom: 8,
|
|
174
|
+
paddingHorizontal: 4,
|
|
117
175
|
},
|
|
118
176
|
factorsList: {
|
|
119
177
|
gap: 8,
|
|
120
178
|
},
|
|
179
|
+
factorContent: {
|
|
180
|
+
flexDirection: 'row',
|
|
181
|
+
alignItems: 'center',
|
|
182
|
+
gap: 8,
|
|
183
|
+
},
|
|
121
184
|
factorButton: {
|
|
122
185
|
padding: 16,
|
|
123
186
|
borderRadius: 8,
|
|
124
187
|
borderWidth: 1,
|
|
125
188
|
},
|
|
126
189
|
factorHeaderText: {
|
|
127
|
-
fontSize:
|
|
190
|
+
fontSize: 16,
|
|
128
191
|
fontWeight: 'bold',
|
|
129
192
|
opacity: 0.8,
|
|
130
193
|
},
|
|
@@ -5,6 +5,7 @@ import { useBackend } from './backend'
|
|
|
5
5
|
|
|
6
6
|
export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendSmsCode: boolean) => {
|
|
7
7
|
const [code, setCode] = useState('')
|
|
8
|
+
const [sendingCode, setSendingCode] = useState(false)
|
|
8
9
|
const [verifying, setVerifying] = useState(false)
|
|
9
10
|
const [error, setError] = useState('')
|
|
10
11
|
|
|
@@ -15,14 +16,22 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
15
16
|
|
|
16
17
|
const initSendCode = useRef(!!automaticallySendSmsCode)
|
|
17
18
|
|
|
18
|
-
const { showSuccess, showError
|
|
19
|
+
const { showSuccess, showError } = useToast()
|
|
19
20
|
|
|
20
21
|
const sendCode = useCallback(async () => {
|
|
21
22
|
if (!enrollmentFactors) {
|
|
22
23
|
showError('Error - No session found')
|
|
23
24
|
return
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
setSendingCode(true)
|
|
27
|
+
return auth.sendMultiFactorCode(factor, enrollmentFactors.multiFactorResolver)
|
|
28
|
+
.then(() => {
|
|
29
|
+
setSendingCode(false)
|
|
30
|
+
})
|
|
31
|
+
.catch((e) => {
|
|
32
|
+
setSendingCode(false)
|
|
33
|
+
setError(e.message || 'An error occurred')
|
|
34
|
+
})
|
|
26
35
|
}, [auth, factor, twoFactorVerification, showError])
|
|
27
36
|
|
|
28
37
|
const initSendCodeFunc = useRef(sendCode)
|
|
@@ -32,7 +41,7 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
32
41
|
}
|
|
33
42
|
}, [])
|
|
34
43
|
|
|
35
|
-
const handleVerify = useCallback(() => {
|
|
44
|
+
const handleVerify = useCallback(async () => {
|
|
36
45
|
setVerifying(true)
|
|
37
46
|
setError('')
|
|
38
47
|
if (!twoFactorVerification) {
|
|
@@ -54,7 +63,7 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
54
63
|
showError('Error - Two factor verification is not supported')
|
|
55
64
|
return
|
|
56
65
|
}
|
|
57
|
-
verify(twoFactorVerification, code)
|
|
66
|
+
return verify(twoFactorVerification, code)
|
|
58
67
|
.then(() => {
|
|
59
68
|
setVerifying(false)
|
|
60
69
|
setCode('')
|
|
@@ -69,7 +78,9 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
69
78
|
return {
|
|
70
79
|
code,
|
|
71
80
|
setCode,
|
|
81
|
+
sendCode,
|
|
72
82
|
verifying,
|
|
83
|
+
sendingCode,
|
|
73
84
|
error,
|
|
74
85
|
handleVerify,
|
|
75
86
|
}
|