@onairos/react-native 3.0.29 → 3.0.31
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/PinInput.js +1 -1
- package/lib/commonjs/components/PinInput.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +6 -2
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/components/onboarding/OAuthWebView.js +217 -94
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/services/platformAuthService.js +48 -6
- package/lib/commonjs/services/platformAuthService.js.map +1 -1
- package/lib/module/components/PinInput.js +1 -1
- package/lib/module/components/PinInput.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +6 -2
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +219 -96
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/services/platformAuthService.js +48 -6
- package/lib/module/services/platformAuthService.js.map +1 -1
- package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts +7 -1
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
- package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/PinInput.tsx +1 -1
- package/src/components/UniversalOnboarding.tsx +5 -1
- package/src/components/onboarding/OAuthWebView.tsx +254 -116
- package/src/services/platformAuthService.ts +45 -5
|
@@ -1,92 +1,218 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import React, { useState, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
ActivityIndicator,
|
|
8
|
+
SafeAreaView,
|
|
9
|
+
Dimensions,
|
|
10
|
+
Linking,
|
|
11
|
+
} from 'react-native';
|
|
12
|
+
import { WebView } from 'react-native-webview';
|
|
4
13
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
5
14
|
import { COLORS } from '../../constants';
|
|
6
|
-
|
|
15
|
+
|
|
16
|
+
const { width, height } = Dimensions.get('window');
|
|
17
|
+
|
|
18
|
+
export interface OAuthWebViewProps {
|
|
19
|
+
url: string;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
onSuccess: (code: string) => void;
|
|
22
|
+
platform?: string;
|
|
23
|
+
onComplete?: () => void;
|
|
24
|
+
}
|
|
7
25
|
|
|
8
26
|
export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
9
27
|
url,
|
|
10
|
-
platform,
|
|
11
|
-
onComplete,
|
|
12
28
|
onClose,
|
|
13
29
|
onSuccess,
|
|
30
|
+
platform = 'platform',
|
|
31
|
+
onComplete,
|
|
14
32
|
}) => {
|
|
15
|
-
const [
|
|
33
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
34
|
+
const [error, setError] = useState<string | null>(null);
|
|
35
|
+
const webViewRef = useRef<WebView>(null);
|
|
36
|
+
|
|
37
|
+
console.log('Opening OAuth WebView with URL:', url);
|
|
16
38
|
|
|
17
|
-
const handleNavigationStateChange =
|
|
18
|
-
(
|
|
19
|
-
|
|
39
|
+
const handleNavigationStateChange = (navState: any) => {
|
|
40
|
+
console.log(`Navigation state changed for ${platform}:`, navState.url);
|
|
41
|
+
|
|
42
|
+
// Check for the final redirect to onairos.uk domain (this means backend callback completed)
|
|
43
|
+
const isFinalRedirect = (
|
|
44
|
+
navState.url.includes('onairos.uk/Home') ||
|
|
45
|
+
navState.url.includes('onairos.uk/home') ||
|
|
46
|
+
navState.url.includes('onairos.uk/success') ||
|
|
47
|
+
navState.url.startsWith('https://onairos.uk/Home')
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Platform-specific success patterns
|
|
51
|
+
const platformSuccessPatterns: Record<string, RegExp[]> = {
|
|
52
|
+
reddit: [
|
|
53
|
+
/reddit\.com\/api\/v1\/authorize\?done=true/,
|
|
54
|
+
/reddit\.com\/api\/v1\/authorize\/success/
|
|
55
|
+
],
|
|
56
|
+
pinterest: [
|
|
57
|
+
/pinterest\.com\/oauth\/success/,
|
|
58
|
+
/pinterest\.com\/oauth\/complete/
|
|
59
|
+
],
|
|
60
|
+
linkedin: [
|
|
61
|
+
/linkedin\.com\/oauth\/success/,
|
|
62
|
+
/linkedin\.com\/oauth\/complete/,
|
|
63
|
+
/linkedin\.com\/uas\/oauth2\/authorization\/success/
|
|
64
|
+
],
|
|
65
|
+
email: [/success/],
|
|
66
|
+
instagram: [
|
|
67
|
+
/instagram\.com\/oauth\/authorize\?done=true/,
|
|
68
|
+
/instagram\.com\/oauth\/success/
|
|
69
|
+
],
|
|
70
|
+
youtube: [
|
|
71
|
+
/accounts\.google\.com\/o\/oauth2\/approval/,
|
|
72
|
+
/youtube\.com\/oauth\/success/
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Check for platform-specific success patterns
|
|
77
|
+
const isPlatformSuccess = platform && platformSuccessPatterns[platform] ?
|
|
78
|
+
platformSuccessPatterns[platform].some(pattern => pattern.test(navState.url)) :
|
|
79
|
+
false;
|
|
80
|
+
|
|
81
|
+
// Check for callback URLs that might contain the authorization code
|
|
82
|
+
const isCallbackUrl = (
|
|
83
|
+
navState.url.includes('/callback') ||
|
|
84
|
+
navState.url.includes('code=') ||
|
|
85
|
+
navState.url.includes('token=') ||
|
|
86
|
+
navState.url.includes('access_token=')
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Extract authorization code or token if present
|
|
90
|
+
let authCode = null;
|
|
91
|
+
if (isCallbackUrl) {
|
|
92
|
+
console.log('Detected callback URL with possible code/token');
|
|
20
93
|
|
|
21
|
-
//
|
|
22
|
-
const
|
|
94
|
+
// Try to extract code or token using different patterns
|
|
95
|
+
const codeMatch = navState.url.match(/code=([^&]+)/);
|
|
96
|
+
const tokenMatch = navState.url.match(/(?:token|access_token)=([^&]+)/);
|
|
23
97
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Check for platform-specific success patterns
|
|
33
|
-
const isYouTubeSuccess = (
|
|
34
|
-
platform === 'youtube' &&
|
|
35
|
-
navState.url.includes('accounts.google.com/o/oauth2/approval')
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const isLinkedInSuccess = (
|
|
39
|
-
platform === 'linkedin' &&
|
|
40
|
-
navState.url.includes('linkedin.com/oauth/v2/authorization/success')
|
|
41
|
-
);
|
|
98
|
+
if (codeMatch && codeMatch[1]) {
|
|
99
|
+
authCode = codeMatch[1];
|
|
100
|
+
console.log('OAuth code extracted:', authCode);
|
|
101
|
+
} else if (tokenMatch && tokenMatch[1]) {
|
|
102
|
+
authCode = tokenMatch[1];
|
|
103
|
+
console.log('OAuth token extracted:', authCode);
|
|
104
|
+
}
|
|
42
105
|
|
|
43
|
-
//
|
|
44
|
-
|
|
106
|
+
// Call onSuccess with the extracted code/token
|
|
107
|
+
if (authCode) {
|
|
108
|
+
onSuccess(authCode);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// If we see the final redirect or platform-specific success, close the OAuth window
|
|
113
|
+
if (isFinalRedirect || isPlatformSuccess) {
|
|
114
|
+
console.log(`Detected success for ${platform}`);
|
|
45
115
|
|
|
46
|
-
// If we
|
|
47
|
-
if (
|
|
116
|
+
// If we haven't already extracted a code/token, consider this a generic success
|
|
117
|
+
if (!authCode) {
|
|
48
118
|
onSuccess('success');
|
|
49
|
-
if (onComplete) {
|
|
50
|
-
onComplete();
|
|
51
|
-
}
|
|
52
|
-
return;
|
|
53
|
-
} else if (isCallbackUrl) {
|
|
54
|
-
// Extract the authorization code
|
|
55
|
-
const authCode = extractAuthCode(navState.url);
|
|
56
|
-
if (authCode) {
|
|
57
|
-
onSuccess(authCode);
|
|
58
|
-
if (onComplete) {
|
|
59
|
-
onComplete();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return;
|
|
63
119
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
120
|
+
|
|
121
|
+
// Close the OAuth window
|
|
122
|
+
if (onComplete) {
|
|
123
|
+
console.log('Calling onComplete to close OAuth window');
|
|
124
|
+
onComplete();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
67
128
|
|
|
68
|
-
const handleLoadEnd =
|
|
69
|
-
|
|
70
|
-
|
|
129
|
+
const handleLoadEnd = () => {
|
|
130
|
+
setIsLoading(false);
|
|
131
|
+
setError(null);
|
|
132
|
+
};
|
|
71
133
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
134
|
+
const handleError = (syntheticEvent: any) => {
|
|
135
|
+
const { nativeEvent } = syntheticEvent;
|
|
136
|
+
console.error('WebView error:', nativeEvent);
|
|
137
|
+
setError('Failed to load OAuth page. Please try again.');
|
|
138
|
+
setIsLoading(false);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const handleOpenInBrowser = () => {
|
|
142
|
+
Linking.openURL(url).catch(err => {
|
|
143
|
+
console.error('Failed to open URL in browser:', err);
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get platform-specific icon
|
|
149
|
+
*/
|
|
150
|
+
const getPlatformIcon = (platform: string): string => {
|
|
151
|
+
switch (platform) {
|
|
152
|
+
case 'instagram':
|
|
153
|
+
return 'photo-camera';
|
|
154
|
+
case 'youtube':
|
|
155
|
+
return 'smart-display';
|
|
156
|
+
case 'pinterest':
|
|
157
|
+
return 'push-pin';
|
|
158
|
+
case 'reddit':
|
|
159
|
+
return 'forum';
|
|
160
|
+
case 'email':
|
|
161
|
+
return 'email';
|
|
162
|
+
default:
|
|
163
|
+
return 'link';
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get platform-specific color
|
|
169
|
+
*/
|
|
170
|
+
const getPlatformColor = (platform: string): string => {
|
|
171
|
+
switch (platform) {
|
|
172
|
+
case 'instagram':
|
|
173
|
+
return '#E1306C';
|
|
174
|
+
case 'youtube':
|
|
175
|
+
return '#FF0000';
|
|
176
|
+
case 'pinterest':
|
|
177
|
+
return '#E60023';
|
|
178
|
+
case 'reddit':
|
|
179
|
+
return '#FF4500';
|
|
180
|
+
case 'email':
|
|
181
|
+
return '#4285F4';
|
|
182
|
+
default:
|
|
183
|
+
return COLORS.primary;
|
|
87
184
|
}
|
|
88
185
|
};
|
|
89
186
|
|
|
187
|
+
if (error) {
|
|
188
|
+
return (
|
|
189
|
+
<SafeAreaView style={styles.container}>
|
|
190
|
+
<View style={styles.header}>
|
|
191
|
+
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
|
192
|
+
<Icon name="close" size={24} color="#000" />
|
|
193
|
+
</TouchableOpacity>
|
|
194
|
+
<View style={styles.titleContainer}>
|
|
195
|
+
<Icon
|
|
196
|
+
name={getPlatformIcon(platform)}
|
|
197
|
+
size={20}
|
|
198
|
+
color={getPlatformColor(platform)}
|
|
199
|
+
/>
|
|
200
|
+
<Text style={styles.titleText}>{platform.charAt(0).toUpperCase() + platform.slice(1)} OAuth</Text>
|
|
201
|
+
</View>
|
|
202
|
+
</View>
|
|
203
|
+
|
|
204
|
+
<View style={styles.errorContainer}>
|
|
205
|
+
<Icon name="error-outline" size={48} color="#FF6B6B" />
|
|
206
|
+
<Text style={styles.errorTitle}>Connection Error</Text>
|
|
207
|
+
<Text style={styles.errorMessage}>{error}</Text>
|
|
208
|
+
<TouchableOpacity style={styles.retryButton} onPress={handleOpenInBrowser}>
|
|
209
|
+
<Text style={styles.retryButtonText}>Open in Browser</Text>
|
|
210
|
+
</TouchableOpacity>
|
|
211
|
+
</View>
|
|
212
|
+
</SafeAreaView>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
90
216
|
return (
|
|
91
217
|
<SafeAreaView style={styles.container}>
|
|
92
218
|
<View style={styles.header}>
|
|
@@ -95,76 +221,39 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
95
221
|
</TouchableOpacity>
|
|
96
222
|
<View style={styles.titleContainer}>
|
|
97
223
|
<Icon
|
|
98
|
-
name={getPlatformIcon(platform
|
|
224
|
+
name={getPlatformIcon(platform)}
|
|
99
225
|
size={20}
|
|
100
|
-
color={getPlatformColor(platform
|
|
226
|
+
color={getPlatformColor(platform)}
|
|
101
227
|
/>
|
|
228
|
+
<Text style={styles.titleText}>{platform.charAt(0).toUpperCase() + platform.slice(1)} OAuth</Text>
|
|
102
229
|
</View>
|
|
230
|
+
<TouchableOpacity onPress={handleOpenInBrowser} style={styles.browserButton}>
|
|
231
|
+
<Icon name="open-in-browser" size={20} color="#666" />
|
|
232
|
+
</TouchableOpacity>
|
|
103
233
|
</View>
|
|
104
234
|
|
|
105
235
|
<WebView
|
|
236
|
+
ref={webViewRef}
|
|
106
237
|
source={{ uri: url }}
|
|
107
238
|
onNavigationStateChange={handleNavigationStateChange}
|
|
108
239
|
onLoadEnd={handleLoadEnd}
|
|
109
|
-
|
|
240
|
+
onError={handleError}
|
|
110
241
|
style={styles.webView}
|
|
111
242
|
javaScriptEnabled={true}
|
|
112
243
|
domStorageEnabled={true}
|
|
113
|
-
sharedCookiesEnabled={true}
|
|
114
|
-
thirdPartyCookiesEnabled={true}
|
|
115
|
-
allowsInlineMediaPlayback={true}
|
|
116
|
-
mediaPlaybackRequiresUserAction={false}
|
|
117
244
|
userAgent="Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"
|
|
118
|
-
mixedContentMode="compatibility"
|
|
119
|
-
allowsFullscreenVideo={true}
|
|
120
|
-
allowsProtectedMedia={true}
|
|
121
245
|
/>
|
|
122
246
|
|
|
123
|
-
{
|
|
247
|
+
{isLoading && (
|
|
124
248
|
<View style={styles.loadingContainer}>
|
|
125
249
|
<ActivityIndicator size="large" color={COLORS.primary} />
|
|
250
|
+
<Text style={styles.loadingText}>Loading {platform}...</Text>
|
|
126
251
|
</View>
|
|
127
252
|
)}
|
|
128
253
|
</SafeAreaView>
|
|
129
254
|
);
|
|
130
255
|
};
|
|
131
256
|
|
|
132
|
-
/**
|
|
133
|
-
* Get platform-specific icon
|
|
134
|
-
*/
|
|
135
|
-
const getPlatformIcon = (platform: string): string => {
|
|
136
|
-
switch (platform) {
|
|
137
|
-
case 'instagram':
|
|
138
|
-
return 'photo-camera';
|
|
139
|
-
case 'youtube':
|
|
140
|
-
return 'smart-display';
|
|
141
|
-
case 'pinterest':
|
|
142
|
-
return 'push-pin';
|
|
143
|
-
case 'reddit':
|
|
144
|
-
return 'forum';
|
|
145
|
-
default:
|
|
146
|
-
return 'link';
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Get platform-specific color
|
|
152
|
-
*/
|
|
153
|
-
const getPlatformColor = (platform: string): string => {
|
|
154
|
-
switch (platform) {
|
|
155
|
-
case 'instagram':
|
|
156
|
-
return '#E1306C';
|
|
157
|
-
case 'youtube':
|
|
158
|
-
return '#FF0000';
|
|
159
|
-
case 'pinterest':
|
|
160
|
-
return '#E60023';
|
|
161
|
-
case 'reddit':
|
|
162
|
-
return '#FF4500';
|
|
163
|
-
default:
|
|
164
|
-
return COLORS.primary;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
|
|
168
257
|
const styles = StyleSheet.create({
|
|
169
258
|
container: {
|
|
170
259
|
flex: 1,
|
|
@@ -181,7 +270,15 @@ const styles = StyleSheet.create({
|
|
|
181
270
|
},
|
|
182
271
|
titleContainer: {
|
|
183
272
|
flex: 1,
|
|
273
|
+
flexDirection: 'row',
|
|
184
274
|
alignItems: 'center',
|
|
275
|
+
justifyContent: 'center',
|
|
276
|
+
},
|
|
277
|
+
titleText: {
|
|
278
|
+
marginLeft: 8,
|
|
279
|
+
fontSize: 16,
|
|
280
|
+
fontWeight: '500',
|
|
281
|
+
color: '#000',
|
|
185
282
|
},
|
|
186
283
|
closeButton: {
|
|
187
284
|
padding: 8,
|
|
@@ -189,6 +286,12 @@ const styles = StyleSheet.create({
|
|
|
189
286
|
left: 16,
|
|
190
287
|
zIndex: 10,
|
|
191
288
|
},
|
|
289
|
+
browserButton: {
|
|
290
|
+
padding: 8,
|
|
291
|
+
position: 'absolute',
|
|
292
|
+
right: 16,
|
|
293
|
+
zIndex: 10,
|
|
294
|
+
},
|
|
192
295
|
webView: {
|
|
193
296
|
flex: 1,
|
|
194
297
|
},
|
|
@@ -198,4 +301,39 @@ const styles = StyleSheet.create({
|
|
|
198
301
|
alignItems: 'center',
|
|
199
302
|
justifyContent: 'center',
|
|
200
303
|
},
|
|
304
|
+
loadingText: {
|
|
305
|
+
marginTop: 10,
|
|
306
|
+
fontSize: 16,
|
|
307
|
+
color: '#666',
|
|
308
|
+
},
|
|
309
|
+
errorContainer: {
|
|
310
|
+
flex: 1,
|
|
311
|
+
alignItems: 'center',
|
|
312
|
+
justifyContent: 'center',
|
|
313
|
+
padding: 20,
|
|
314
|
+
},
|
|
315
|
+
errorTitle: {
|
|
316
|
+
fontSize: 18,
|
|
317
|
+
fontWeight: '600',
|
|
318
|
+
color: '#333',
|
|
319
|
+
marginTop: 16,
|
|
320
|
+
marginBottom: 8,
|
|
321
|
+
},
|
|
322
|
+
errorMessage: {
|
|
323
|
+
fontSize: 14,
|
|
324
|
+
color: '#666',
|
|
325
|
+
textAlign: 'center',
|
|
326
|
+
marginBottom: 20,
|
|
327
|
+
},
|
|
328
|
+
retryButton: {
|
|
329
|
+
backgroundColor: COLORS.primary,
|
|
330
|
+
paddingHorizontal: 24,
|
|
331
|
+
paddingVertical: 12,
|
|
332
|
+
borderRadius: 8,
|
|
333
|
+
},
|
|
334
|
+
retryButtonText: {
|
|
335
|
+
color: '#fff',
|
|
336
|
+
fontSize: 16,
|
|
337
|
+
fontWeight: '600',
|
|
338
|
+
},
|
|
201
339
|
});
|
|
@@ -166,13 +166,53 @@ export const initiateNativeAuth = async (platform: string): Promise<boolean> =>
|
|
|
166
166
|
try {
|
|
167
167
|
// Currently only YouTube (Google Sign-In) is supported
|
|
168
168
|
if (platform === 'youtube') {
|
|
169
|
-
// This is a placeholder for the actual implementation
|
|
170
|
-
// In a real implementation, you would import and use the Google Sign-In SDK
|
|
171
169
|
console.log('Initiating native Google Sign-In for YouTube');
|
|
172
170
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
try {
|
|
172
|
+
// Import Google Sign-In dynamically to avoid errors if not installed
|
|
173
|
+
const { GoogleSignin, statusCodes } = require('@react-native-google-signin/google-signin');
|
|
174
|
+
|
|
175
|
+
// Configure Google Sign-In
|
|
176
|
+
await GoogleSignin.configure({
|
|
177
|
+
scopes: ['https://www.googleapis.com/auth/youtube.readonly'],
|
|
178
|
+
webClientId: 'YOUR_WEB_CLIENT_ID', // Replace with your actual web client ID
|
|
179
|
+
offlineAccess: true,
|
|
180
|
+
hostedDomain: '',
|
|
181
|
+
forceCodeForRefreshToken: true,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Check if device supports Google Play Services
|
|
185
|
+
await GoogleSignin.hasPlayServices();
|
|
186
|
+
|
|
187
|
+
// Sign in
|
|
188
|
+
const userInfo = await GoogleSignin.signIn();
|
|
189
|
+
console.log('Google Sign-In successful:', userInfo);
|
|
190
|
+
|
|
191
|
+
// Get access token
|
|
192
|
+
const tokens = await GoogleSignin.getTokens();
|
|
193
|
+
console.log('Google tokens:', tokens);
|
|
194
|
+
|
|
195
|
+
// Here you would typically send the tokens to your backend
|
|
196
|
+
// to associate the YouTube account with the user
|
|
197
|
+
|
|
198
|
+
return true;
|
|
199
|
+
} catch (error: any) {
|
|
200
|
+
console.error('Google Sign-In error:', error);
|
|
201
|
+
|
|
202
|
+
const { statusCodes: StatusCodes } = require('@react-native-google-signin/google-signin');
|
|
203
|
+
|
|
204
|
+
if (error.code === StatusCodes.SIGN_IN_CANCELLED) {
|
|
205
|
+
console.log('User cancelled the sign-in flow');
|
|
206
|
+
} else if (error.code === StatusCodes.IN_PROGRESS) {
|
|
207
|
+
console.log('Sign-in is in progress already');
|
|
208
|
+
} else if (error.code === StatusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
|
|
209
|
+
console.log('Play services not available or outdated');
|
|
210
|
+
} else {
|
|
211
|
+
console.log('Some other error happened');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
176
216
|
}
|
|
177
217
|
|
|
178
218
|
throw new Error(`Native authentication not supported for ${platform}`);
|