@onairos/react-native 3.0.69 → 3.0.70
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/onboarding/OAuthWebView.js +156 -10
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/services/platformAuthService.js +189 -44
- package/lib/commonjs/services/platformAuthService.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +156 -10
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/services/platformAuthService.js +188 -43
- package/lib/module/services/platformAuthService.js.map +1 -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/onboarding/OAuthWebView.tsx +137 -6
- package/src/services/platformAuthService.ts +204 -39
|
@@ -177,49 +177,87 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
177
177
|
|
|
178
178
|
// Check for specific NSURLErrorDomain codes
|
|
179
179
|
let errorMessage = 'Failed to load OAuth page.';
|
|
180
|
+
let isRetryable = true;
|
|
180
181
|
|
|
181
182
|
if (nativeEvent.domain === 'NSURLErrorDomain') {
|
|
182
183
|
switch (nativeEvent.code) {
|
|
183
184
|
case -1009: // NSURLErrorNotConnectedToInternet
|
|
184
185
|
errorMessage = 'No internet connection. Please check your network and try again.';
|
|
186
|
+
isRetryable = true;
|
|
185
187
|
break;
|
|
186
188
|
case -1003: // NSURLErrorCannotFindHost
|
|
187
189
|
errorMessage = 'Cannot reach authentication server. Please check your internet connection.';
|
|
190
|
+
isRetryable = true;
|
|
188
191
|
break;
|
|
189
192
|
case -1001: // NSURLErrorTimedOut
|
|
190
193
|
errorMessage = 'Connection timed out. Please try again.';
|
|
194
|
+
isRetryable = true;
|
|
191
195
|
break;
|
|
192
196
|
case -1200: // NSURLErrorSecureConnectionFailed
|
|
193
197
|
errorMessage = 'Secure connection failed. Please try again.';
|
|
198
|
+
isRetryable = true;
|
|
194
199
|
break;
|
|
195
200
|
case -1022: // NSURLErrorAppTransportSecurityRequiresSecureConnection
|
|
196
201
|
errorMessage = 'App Transport Security error. Connection must be secure.';
|
|
202
|
+
isRetryable = false;
|
|
197
203
|
break;
|
|
198
204
|
case -1004: // NSURLErrorCannotConnectToHost
|
|
199
205
|
errorMessage = 'Cannot connect to authentication server. Please try again later.';
|
|
206
|
+
isRetryable = true;
|
|
207
|
+
break;
|
|
208
|
+
case -1005: // NSURLErrorNetworkConnectionLost
|
|
209
|
+
errorMessage = 'Network connection lost. Please check your connection and try again.';
|
|
210
|
+
isRetryable = true;
|
|
211
|
+
break;
|
|
212
|
+
case -1020: // NSURLErrorDataNotAllowed
|
|
213
|
+
errorMessage = 'Data not allowed. Please check your cellular data settings.';
|
|
214
|
+
isRetryable = true;
|
|
200
215
|
break;
|
|
201
216
|
default:
|
|
202
217
|
errorMessage = `Network error (${nativeEvent.code}): ${nativeEvent.description || 'Please check your connection and try again.'}`;
|
|
218
|
+
isRetryable = true;
|
|
219
|
+
}
|
|
220
|
+
} else if (nativeEvent.domain === 'WebKitErrorDomain') {
|
|
221
|
+
switch (nativeEvent.code) {
|
|
222
|
+
case 102: // WebKitErrorFrameLoadInterruptedByPolicyChange
|
|
223
|
+
errorMessage = 'Page load was interrupted. Please try again.';
|
|
224
|
+
isRetryable = true;
|
|
225
|
+
break;
|
|
226
|
+
case 204: // WebKitErrorPlugInLoadFailed
|
|
227
|
+
errorMessage = 'Plugin failed to load. Please try again.';
|
|
228
|
+
isRetryable = true;
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
errorMessage = `WebKit error (${nativeEvent.code}): ${nativeEvent.description || 'Please try again.'}`;
|
|
232
|
+
isRetryable = true;
|
|
203
233
|
}
|
|
204
234
|
}
|
|
205
235
|
|
|
206
236
|
console.error('🔴 OAuth WebView Error:', errorMessage);
|
|
207
237
|
|
|
208
|
-
|
|
209
|
-
|
|
238
|
+
// Implement smart retry logic
|
|
239
|
+
if (isRetryable && retryCount < 3) {
|
|
240
|
+
console.log(`🔄 Auto-retrying OAuth load (attempt ${retryCount + 1}/3) in 3 seconds...`);
|
|
210
241
|
setRetryCount(prev => prev + 1);
|
|
211
242
|
setIsLoading(true);
|
|
212
243
|
setError(null);
|
|
213
244
|
|
|
214
|
-
// Retry after a
|
|
245
|
+
// Retry after a delay with exponential backoff
|
|
246
|
+
const retryDelay = 3000 * Math.pow(2, retryCount); // 3s, 6s, 12s
|
|
215
247
|
setTimeout(() => {
|
|
216
248
|
if (webViewRef.current) {
|
|
249
|
+
console.log(`🔄 Attempting retry ${retryCount + 1}...`);
|
|
217
250
|
webViewRef.current.reload();
|
|
218
251
|
}
|
|
219
|
-
},
|
|
252
|
+
}, retryDelay);
|
|
220
253
|
} else {
|
|
221
254
|
setError(errorMessage);
|
|
222
|
-
|
|
255
|
+
setIsLoading(false);
|
|
256
|
+
|
|
257
|
+
// Show additional help for persistent errors
|
|
258
|
+
if (retryCount >= 3) {
|
|
259
|
+
console.log('❌ Maximum retries reached, showing error to user');
|
|
260
|
+
}
|
|
223
261
|
}
|
|
224
262
|
};
|
|
225
263
|
|
|
@@ -303,14 +341,66 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
303
341
|
<Icon name="error-outline" size={48} color="#FF6B6B" />
|
|
304
342
|
<Text style={styles.errorTitle}>Connection Error</Text>
|
|
305
343
|
<Text style={styles.errorMessage}>{error}</Text>
|
|
344
|
+
|
|
345
|
+
{/* Help text based on error type */}
|
|
346
|
+
{error.includes('internet') || error.includes('network') ? (
|
|
347
|
+
<View style={styles.helpContainer}>
|
|
348
|
+
<Text style={styles.helpTitle}>💡 Troubleshooting Steps:</Text>
|
|
349
|
+
<Text style={styles.helpText}>• Check your Wi-Fi or cellular connection</Text>
|
|
350
|
+
<Text style={styles.helpText}>• Try switching between Wi-Fi and cellular</Text>
|
|
351
|
+
<Text style={styles.helpText}>• Ensure you're not using a VPN that blocks OAuth</Text>
|
|
352
|
+
<Text style={styles.helpText}>• Close other apps that might be using bandwidth</Text>
|
|
353
|
+
</View>
|
|
354
|
+
) : error.includes('timeout') ? (
|
|
355
|
+
<View style={styles.helpContainer}>
|
|
356
|
+
<Text style={styles.helpTitle}>⏱️ Connection Timeout:</Text>
|
|
357
|
+
<Text style={styles.helpText}>• Your connection might be slow</Text>
|
|
358
|
+
<Text style={styles.helpText}>• Try again when you have a stronger signal</Text>
|
|
359
|
+
<Text style={styles.helpText}>• Use "Open in Browser" for better reliability</Text>
|
|
360
|
+
</View>
|
|
361
|
+
) : error.includes('secure') || error.includes('SSL') ? (
|
|
362
|
+
<View style={styles.helpContainer}>
|
|
363
|
+
<Text style={styles.helpTitle}>🔒 Security Error:</Text>
|
|
364
|
+
<Text style={styles.helpText}>• Check your device's date and time settings</Text>
|
|
365
|
+
<Text style={styles.helpText}>• Update your device's operating system</Text>
|
|
366
|
+
<Text style={styles.helpText}>• Try "Open in Browser" as an alternative</Text>
|
|
367
|
+
</View>
|
|
368
|
+
) : (
|
|
369
|
+
<View style={styles.helpContainer}>
|
|
370
|
+
<Text style={styles.helpTitle}>🔧 General Solutions:</Text>
|
|
371
|
+
<Text style={styles.helpText}>• Close and reopen the app</Text>
|
|
372
|
+
<Text style={styles.helpText}>• Check your internet connection</Text>
|
|
373
|
+
<Text style={styles.helpText}>• Use "Open in Browser" for better reliability</Text>
|
|
374
|
+
</View>
|
|
375
|
+
)}
|
|
376
|
+
|
|
306
377
|
<View style={styles.buttonContainer}>
|
|
307
378
|
<TouchableOpacity style={styles.retryButton} onPress={handleRetry}>
|
|
379
|
+
<Icon name="refresh" size={20} color="#fff" style={styles.buttonIcon} />
|
|
308
380
|
<Text style={styles.retryButtonText}>Retry</Text>
|
|
309
381
|
</TouchableOpacity>
|
|
310
382
|
<TouchableOpacity style={styles.browserButton} onPress={handleOpenInBrowser}>
|
|
383
|
+
<Icon name="open-in-browser" size={20} color="#666" style={styles.buttonIcon} />
|
|
311
384
|
<Text style={styles.browserButtonText}>Open in Browser</Text>
|
|
312
|
-
|
|
385
|
+
</TouchableOpacity>
|
|
313
386
|
</View>
|
|
387
|
+
|
|
388
|
+
{retryCount >= 3 && (
|
|
389
|
+
<View style={styles.persistentErrorContainer}>
|
|
390
|
+
<Text style={styles.persistentErrorText}>
|
|
391
|
+
Still having trouble? Try these steps:
|
|
392
|
+
</Text>
|
|
393
|
+
<Text style={styles.persistentErrorStep}>
|
|
394
|
+
1. Use "Open in Browser" for more reliable authentication
|
|
395
|
+
</Text>
|
|
396
|
+
<Text style={styles.persistentErrorStep}>
|
|
397
|
+
2. Check if other apps can access the internet
|
|
398
|
+
</Text>
|
|
399
|
+
<Text style={styles.persistentErrorStep}>
|
|
400
|
+
3. Restart your device if the problem persists
|
|
401
|
+
</Text>
|
|
402
|
+
</View>
|
|
403
|
+
)}
|
|
314
404
|
</View>
|
|
315
405
|
</SafeAreaView>
|
|
316
406
|
);
|
|
@@ -469,6 +559,9 @@ const styles = StyleSheet.create({
|
|
|
469
559
|
paddingHorizontal: 24,
|
|
470
560
|
paddingVertical: 12,
|
|
471
561
|
borderRadius: 8,
|
|
562
|
+
flexDirection: 'row',
|
|
563
|
+
alignItems: 'center',
|
|
564
|
+
justifyContent: 'center',
|
|
472
565
|
},
|
|
473
566
|
webView: {
|
|
474
567
|
flex: 1,
|
|
@@ -509,6 +602,9 @@ const styles = StyleSheet.create({
|
|
|
509
602
|
paddingVertical: 12,
|
|
510
603
|
borderRadius: 8,
|
|
511
604
|
marginRight: 10,
|
|
605
|
+
flexDirection: 'row',
|
|
606
|
+
alignItems: 'center',
|
|
607
|
+
justifyContent: 'center',
|
|
512
608
|
},
|
|
513
609
|
retryButtonText: {
|
|
514
610
|
color: '#fff',
|
|
@@ -526,4 +622,39 @@ const styles = StyleSheet.create({
|
|
|
526
622
|
fontSize: 16,
|
|
527
623
|
fontWeight: '600',
|
|
528
624
|
},
|
|
625
|
+
helpContainer: {
|
|
626
|
+
marginBottom: 20,
|
|
627
|
+
},
|
|
628
|
+
helpTitle: {
|
|
629
|
+
fontSize: 18,
|
|
630
|
+
fontWeight: '600',
|
|
631
|
+
color: '#333',
|
|
632
|
+
marginBottom: 8,
|
|
633
|
+
},
|
|
634
|
+
helpText: {
|
|
635
|
+
fontSize: 14,
|
|
636
|
+
color: '#666',
|
|
637
|
+
textAlign: 'center',
|
|
638
|
+
},
|
|
639
|
+
buttonIcon: {
|
|
640
|
+
marginRight: 10,
|
|
641
|
+
},
|
|
642
|
+
persistentErrorContainer: {
|
|
643
|
+
marginTop: 20,
|
|
644
|
+
padding: 20,
|
|
645
|
+
backgroundColor: '#f8f8f8',
|
|
646
|
+
borderRadius: 8,
|
|
647
|
+
},
|
|
648
|
+
persistentErrorText: {
|
|
649
|
+
fontSize: 16,
|
|
650
|
+
fontWeight: '600',
|
|
651
|
+
color: '#333',
|
|
652
|
+
marginBottom: 10,
|
|
653
|
+
},
|
|
654
|
+
persistentErrorStep: {
|
|
655
|
+
fontSize: 14,
|
|
656
|
+
color: '#666',
|
|
657
|
+
textAlign: 'center',
|
|
658
|
+
marginBottom: 5,
|
|
659
|
+
},
|
|
529
660
|
});
|
|
@@ -100,6 +100,17 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
100
100
|
console.log('🌐 Platform uses OAuth WebView flow');
|
|
101
101
|
console.log('🔗 Auth endpoint:', PLATFORM_AUTH_CONFIG[platform].authEndpoint);
|
|
102
102
|
|
|
103
|
+
// Pre-flight connectivity check
|
|
104
|
+
console.log('🔍 Performing pre-flight connectivity check...');
|
|
105
|
+
const connectivityResult = await testApiConnectivity();
|
|
106
|
+
|
|
107
|
+
if (!connectivityResult.success) {
|
|
108
|
+
console.error('❌ Pre-flight connectivity check failed:', connectivityResult.error);
|
|
109
|
+
throw new Error(`Cannot reach authentication server: ${connectivityResult.error}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log('✅ Pre-flight connectivity check passed');
|
|
113
|
+
|
|
103
114
|
// Handle Instagram with specific API format
|
|
104
115
|
if (platform === 'instagram') {
|
|
105
116
|
const state = 'djksbfds';
|
|
@@ -112,13 +123,31 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
112
123
|
|
|
113
124
|
console.log('📤 Sending Instagram OAuth request:', jsonData);
|
|
114
125
|
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
|
128
|
+
|
|
129
|
+
let response: Response;
|
|
130
|
+
try {
|
|
131
|
+
response = await fetch('https://api2.onairos.uk/instagram/authorize', {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
headers: {
|
|
134
|
+
'Content-Type': 'application/json',
|
|
135
|
+
'User-Agent': 'OnairosReactNative/1.0',
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify(jsonData),
|
|
138
|
+
signal: controller.signal,
|
|
139
|
+
});
|
|
140
|
+
} catch (fetchError) {
|
|
141
|
+
clearTimeout(timeoutId);
|
|
142
|
+
|
|
143
|
+
if (fetchError.name === 'AbortError') {
|
|
144
|
+
throw new Error(`Request timeout: Instagram OAuth server took too long to respond`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
throw new Error(`Network error: ${fetchError.message || 'Failed to connect to Instagram OAuth server'}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
clearTimeout(timeoutId);
|
|
122
151
|
|
|
123
152
|
console.log('📡 Instagram OAuth response status:', response.status);
|
|
124
153
|
console.log('📡 Instagram OAuth response headers:', response.headers);
|
|
@@ -134,7 +163,13 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
134
163
|
|
|
135
164
|
if (responseData.instagramURL) {
|
|
136
165
|
console.log('✅ Instagram OAuth URL received:', responseData.instagramURL);
|
|
137
|
-
|
|
166
|
+
|
|
167
|
+
// Validate the URL before returning
|
|
168
|
+
if (await validateOAuthUrl(responseData.instagramURL)) {
|
|
169
|
+
return responseData.instagramURL;
|
|
170
|
+
} else {
|
|
171
|
+
throw new Error('Received invalid Instagram OAuth URL');
|
|
172
|
+
}
|
|
138
173
|
}
|
|
139
174
|
|
|
140
175
|
console.error('❌ No Instagram URL found in response');
|
|
@@ -152,14 +187,32 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
152
187
|
|
|
153
188
|
console.log(`📤 Sending ${platform} OAuth request:`, jsonData);
|
|
154
189
|
|
|
155
|
-
// Make the request to get the OAuth URL
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
190
|
+
// Make the request to get the OAuth URL with enhanced error handling
|
|
191
|
+
const controller = new AbortController();
|
|
192
|
+
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
|
193
|
+
|
|
194
|
+
let response: Response;
|
|
195
|
+
try {
|
|
196
|
+
response = await fetch(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
|
|
197
|
+
method: 'POST',
|
|
198
|
+
headers: {
|
|
199
|
+
'Content-Type': 'application/json',
|
|
200
|
+
'User-Agent': 'OnairosReactNative/1.0',
|
|
201
|
+
},
|
|
202
|
+
body: JSON.stringify(jsonData),
|
|
203
|
+
signal: controller.signal,
|
|
204
|
+
});
|
|
205
|
+
} catch (fetchError) {
|
|
206
|
+
clearTimeout(timeoutId);
|
|
207
|
+
|
|
208
|
+
if (fetchError.name === 'AbortError') {
|
|
209
|
+
throw new Error(`Request timeout: ${platform} OAuth server took too long to respond`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
throw new Error(`Network error: ${fetchError.message || 'Failed to connect to OAuth server'}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
clearTimeout(timeoutId);
|
|
163
216
|
|
|
164
217
|
console.log(`📡 ${platform} OAuth response status:`, response.status);
|
|
165
218
|
console.log(`📡 ${platform} OAuth response headers:`, response.headers);
|
|
@@ -181,36 +234,108 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
181
234
|
}
|
|
182
235
|
|
|
183
236
|
// Check if the response contains the OAuth URL based on platform
|
|
237
|
+
let oauthUrl: string | null = null;
|
|
238
|
+
|
|
184
239
|
switch (platform) {
|
|
185
240
|
case 'reddit':
|
|
186
|
-
|
|
241
|
+
oauthUrl = data.redditURL;
|
|
187
242
|
break;
|
|
188
243
|
case 'pinterest':
|
|
189
|
-
|
|
244
|
+
oauthUrl = data.pinterestURL;
|
|
190
245
|
break;
|
|
191
246
|
case 'youtube':
|
|
192
|
-
|
|
247
|
+
oauthUrl = data.youtubeURL;
|
|
193
248
|
break;
|
|
194
249
|
case 'email':
|
|
195
250
|
// Gmail might return under different field names
|
|
196
|
-
|
|
197
|
-
if (data.gmailURL) return data.gmailURL;
|
|
198
|
-
if (data.authUrl) return data.authUrl;
|
|
199
|
-
if (data.url) return data.url;
|
|
251
|
+
oauthUrl = data.emailURL || data.gmailURL || data.authUrl || data.url;
|
|
200
252
|
break;
|
|
201
253
|
default:
|
|
202
|
-
|
|
254
|
+
oauthUrl = data.url;
|
|
203
255
|
break;
|
|
204
256
|
}
|
|
205
257
|
|
|
206
|
-
|
|
207
|
-
|
|
258
|
+
if (!oauthUrl) {
|
|
259
|
+
console.error(`❌ No OAuth URL found in response for ${platform}. Response:`, data);
|
|
260
|
+
throw new Error(`No OAuth URL found in response for ${platform}`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
console.log(`✅ ${platform} OAuth URL received:`, oauthUrl);
|
|
264
|
+
|
|
265
|
+
// Validate the URL before returning
|
|
266
|
+
if (await validateOAuthUrl(oauthUrl)) {
|
|
267
|
+
return oauthUrl;
|
|
268
|
+
} else {
|
|
269
|
+
throw new Error(`Received invalid ${platform} OAuth URL`);
|
|
270
|
+
}
|
|
208
271
|
} catch (error) {
|
|
209
272
|
console.error(`Error initiating OAuth for ${platform}:`, error);
|
|
210
273
|
throw error;
|
|
211
274
|
}
|
|
212
275
|
};
|
|
213
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Validates an OAuth URL to ensure it's reachable
|
|
279
|
+
* @param url The OAuth URL to validate
|
|
280
|
+
* @returns Promise<boolean> indicating if the URL is valid and reachable
|
|
281
|
+
*/
|
|
282
|
+
const validateOAuthUrl = async (url: string): Promise<boolean> => {
|
|
283
|
+
try {
|
|
284
|
+
console.log('🔍 Validating OAuth URL:', url);
|
|
285
|
+
|
|
286
|
+
// Basic URL format validation
|
|
287
|
+
if (!url || typeof url !== 'string') {
|
|
288
|
+
console.error('❌ Invalid URL format:', url);
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Check if URL starts with https
|
|
293
|
+
if (!url.startsWith('https://')) {
|
|
294
|
+
console.error('❌ URL must use HTTPS:', url);
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Try to parse the URL
|
|
299
|
+
try {
|
|
300
|
+
new URL(url);
|
|
301
|
+
} catch (parseError) {
|
|
302
|
+
console.error('❌ URL parsing failed:', parseError);
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Make a HEAD request to check if the URL is reachable
|
|
307
|
+
const controller = new AbortController();
|
|
308
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const response = await fetch(url, {
|
|
312
|
+
method: 'HEAD',
|
|
313
|
+
signal: controller.signal,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
clearTimeout(timeoutId);
|
|
317
|
+
|
|
318
|
+
// Accept any response that's not a network error
|
|
319
|
+
// OAuth pages might return various status codes
|
|
320
|
+
console.log('✅ OAuth URL validation successful, status:', response.status);
|
|
321
|
+
return true;
|
|
322
|
+
} catch (fetchError) {
|
|
323
|
+
clearTimeout(timeoutId);
|
|
324
|
+
|
|
325
|
+
if (fetchError.name === 'AbortError') {
|
|
326
|
+
console.warn('⚠️ OAuth URL validation timeout, but proceeding anyway');
|
|
327
|
+
return true; // Allow timeout as URLs might be slow to respond
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
console.warn('⚠️ OAuth URL validation failed, but proceeding anyway:', fetchError.message);
|
|
331
|
+
return true; // Allow network errors as they might be temporary
|
|
332
|
+
}
|
|
333
|
+
} catch (error) {
|
|
334
|
+
console.warn('⚠️ OAuth URL validation error, but proceeding anyway:', error);
|
|
335
|
+
return true; // Allow validation errors to not block the flow
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
214
339
|
/**
|
|
215
340
|
* Initiates the native SDK authentication flow for a platform
|
|
216
341
|
* @param platform The platform to authenticate with
|
|
@@ -473,22 +598,62 @@ export const testApiConnectivity = async (): Promise<{ success: boolean; error?:
|
|
|
473
598
|
try {
|
|
474
599
|
console.log('🔍 Testing connectivity to Onairos API...');
|
|
475
600
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
});
|
|
601
|
+
// Test multiple endpoints for better reliability
|
|
602
|
+
const testEndpoints = [
|
|
603
|
+
'https://api2.onairos.uk/health',
|
|
604
|
+
'https://api2.onairos.uk', // Base URL
|
|
605
|
+
];
|
|
482
606
|
|
|
483
|
-
|
|
607
|
+
let lastError: string | null = null;
|
|
484
608
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
609
|
+
for (const endpoint of testEndpoints) {
|
|
610
|
+
try {
|
|
611
|
+
console.log(`🔍 Testing endpoint: ${endpoint}`);
|
|
612
|
+
|
|
613
|
+
const controller = new AbortController();
|
|
614
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
|
|
615
|
+
|
|
616
|
+
const response = await fetch(endpoint, {
|
|
617
|
+
method: 'GET',
|
|
618
|
+
headers: {
|
|
619
|
+
'Content-Type': 'application/json',
|
|
620
|
+
'User-Agent': 'OnairosReactNative/1.0',
|
|
621
|
+
},
|
|
622
|
+
signal: controller.signal,
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
clearTimeout(timeoutId);
|
|
626
|
+
|
|
627
|
+
console.log(`🌐 API connectivity test response for ${endpoint}:`, response.status);
|
|
628
|
+
|
|
629
|
+
if (response.ok || response.status === 404) {
|
|
630
|
+
// Accept 404 as it means the server is reachable
|
|
631
|
+
console.log('✅ API server is reachable');
|
|
632
|
+
return { success: true };
|
|
633
|
+
} else {
|
|
634
|
+
console.log(`⚠️ API server responded with status ${response.status} for ${endpoint}`);
|
|
635
|
+
lastError = `API server error: ${response.status}`;
|
|
636
|
+
// Continue to next endpoint
|
|
637
|
+
}
|
|
638
|
+
} catch (fetchError) {
|
|
639
|
+
console.log(`❌ Failed to reach ${endpoint}:`, fetchError);
|
|
640
|
+
|
|
641
|
+
if (fetchError.name === 'AbortError') {
|
|
642
|
+
lastError = 'Connection timeout - API server took too long to respond';
|
|
643
|
+
} else if (fetchError.message.includes('Network request failed')) {
|
|
644
|
+
lastError = 'Network error - check your internet connection';
|
|
645
|
+
} else if (fetchError.message.includes('not connected to the internet')) {
|
|
646
|
+
lastError = 'No internet connection';
|
|
647
|
+
} else {
|
|
648
|
+
lastError = `Network error: ${fetchError.message}`;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Continue to next endpoint
|
|
652
|
+
}
|
|
491
653
|
}
|
|
654
|
+
|
|
655
|
+
console.error('❌ All API connectivity tests failed');
|
|
656
|
+
return { success: false, error: lastError || 'Cannot reach API server' };
|
|
492
657
|
} catch (error) {
|
|
493
658
|
console.error('❌ API connectivity test failed:', error);
|
|
494
659
|
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
|