@onairos/react-native 3.0.37 → 3.0.39
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/TrainingModal.js +20 -8
- package/lib/commonjs/components/TrainingModal.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +224 -57
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/components/onboarding/OAuthWebView.js +40 -68
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/hooks/useCredentials.js +88 -8
- package/lib/commonjs/hooks/useCredentials.js.map +1 -1
- package/lib/module/components/TrainingModal.js +20 -8
- package/lib/module/components/TrainingModal.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +225 -58
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +40 -68
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/hooks/useCredentials.js +88 -7
- package/lib/module/hooks/useCredentials.js.map +1 -1
- package/lib/typescript/components/TrainingModal.d.ts.map +1 -1
- package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
- package/lib/typescript/hooks/useCredentials.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/TrainingModal.tsx +18 -3
- package/src/components/UniversalOnboarding.tsx +241 -50
- package/src/components/onboarding/OAuthWebView.tsx +51 -113
- package/src/hooks/useCredentials.ts +83 -8
|
@@ -40,7 +40,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
40
40
|
test = false,
|
|
41
41
|
preferredPlatform,
|
|
42
42
|
}) => {
|
|
43
|
-
const [step, setStep] = useState<'connect' | 'pin' | 'training' | 'oauth'>('connect');
|
|
43
|
+
const [step, setStep] = useState<'connect' | 'pin' | 'training' | 'oauth' | 'success'>('connect');
|
|
44
44
|
const [connections, setConnections] = useState<ConnectionStatus>({});
|
|
45
45
|
const [pin, setPin] = useState<string>('');
|
|
46
46
|
const [selectedTier, setSelectedTier] = useState<'Small' | 'Medium' | 'Large'>('Medium');
|
|
@@ -54,6 +54,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
54
54
|
const [currentPlatform, setCurrentPlatform] = useState<string>('');
|
|
55
55
|
const [username, setUsername] = useState<string>('Avatar');
|
|
56
56
|
const [isConnectingPlatform, setIsConnectingPlatform] = useState<boolean>(false);
|
|
57
|
+
const [showLoginWebView, setShowLoginWebView] = useState<boolean>(false);
|
|
57
58
|
|
|
58
59
|
const platforms = [
|
|
59
60
|
{ id: 'instagram', name: 'Instagram', icon: require('../assets/images/instagram.png') },
|
|
@@ -220,33 +221,11 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
220
221
|
* Handles OAuth callback URLs
|
|
221
222
|
*/
|
|
222
223
|
const handleOAuthCallback = useCallback((url: string) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (code && platform) {
|
|
230
|
-
// Update connections state
|
|
231
|
-
setConnections(prev => ({
|
|
232
|
-
...prev,
|
|
233
|
-
[platform]: { userName: username, connected: true }
|
|
234
|
-
}));
|
|
235
|
-
|
|
236
|
-
// Update platform toggles
|
|
237
|
-
setPlatformToggles(prev => ({
|
|
238
|
-
...prev,
|
|
239
|
-
[platform]: true
|
|
240
|
-
}));
|
|
241
|
-
|
|
242
|
-
// Return to the connect step
|
|
243
|
-
setStep('connect');
|
|
244
|
-
}
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.error('Error handling OAuth callback:', error);
|
|
247
|
-
}
|
|
248
|
-
}, [currentPlatform, username]);
|
|
249
|
-
|
|
224
|
+
console.log('OAuth callback received:', url);
|
|
225
|
+
// Handle the OAuth callback here
|
|
226
|
+
// This would typically extract the authorization code and complete the OAuth flow
|
|
227
|
+
}, []);
|
|
228
|
+
|
|
250
229
|
/**
|
|
251
230
|
* Handles completion of the OAuth flow
|
|
252
231
|
*/
|
|
@@ -276,9 +255,70 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
276
255
|
setStep('connect');
|
|
277
256
|
}, [currentPlatform, username]);
|
|
278
257
|
|
|
258
|
+
// Function to handle "Already have an account" button
|
|
259
|
+
const handleAlreadyHaveAccount = useCallback(() => {
|
|
260
|
+
console.log('Already have an account clicked - opening Onairos login WebView');
|
|
261
|
+
setShowLoginWebView(true);
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
// Function to check for existing account (spoofed for now)
|
|
265
|
+
const checkExistingAccount = useCallback(async () => {
|
|
266
|
+
console.log('Checking for existing account...');
|
|
267
|
+
// TODO: Implement actual logic to check cookies/storage for existing account
|
|
268
|
+
// For now, this is spoofed and doesn't do anything
|
|
269
|
+
return false;
|
|
270
|
+
}, []);
|
|
271
|
+
|
|
272
|
+
// Function to handle login WebView completion
|
|
273
|
+
const handleLoginWebViewComplete = useCallback((result?: any) => {
|
|
274
|
+
console.log('Login WebView completed with result:', result);
|
|
275
|
+
setShowLoginWebView(false);
|
|
276
|
+
|
|
277
|
+
// If login was successful (detected existing cookies/session)
|
|
278
|
+
if (result === 'onairos_login_success') {
|
|
279
|
+
console.log('Existing Onairos account detected, skipping onboarding');
|
|
280
|
+
// Skip the entire onboarding flow and call onComplete directly
|
|
281
|
+
onComplete('https://api2.onairos.uk', 'existing-session-token', {
|
|
282
|
+
existingAccount: true,
|
|
283
|
+
username: 'existing_user',
|
|
284
|
+
skipOnboarding: true,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
// If no existing account found, continue with normal onboarding
|
|
288
|
+
}, [onComplete]);
|
|
289
|
+
|
|
279
290
|
const handlePinSubmit = useCallback(async (userPin: string) => {
|
|
280
291
|
setPin(userPin);
|
|
281
292
|
setStep('training');
|
|
293
|
+
|
|
294
|
+
// Save session data for "Never Connect Again" functionality
|
|
295
|
+
try {
|
|
296
|
+
const sessionData = {
|
|
297
|
+
pin: userPin,
|
|
298
|
+
connections,
|
|
299
|
+
platformToggles,
|
|
300
|
+
selectedTier,
|
|
301
|
+
username,
|
|
302
|
+
timestamp: Date.now(),
|
|
303
|
+
appName: AppName,
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// Store session data in secure storage for future use
|
|
307
|
+
console.log('Saving session data for future "Never Connect Again" functionality:', sessionData);
|
|
308
|
+
|
|
309
|
+
// TODO: Implement actual secure storage of session data
|
|
310
|
+
// This would typically involve:
|
|
311
|
+
// 1. Storing encrypted session data locally
|
|
312
|
+
// 2. Setting cookies in WebView for onairos.uk domain
|
|
313
|
+
// 3. Storing authentication tokens securely
|
|
314
|
+
|
|
315
|
+
// For now, we'll simulate this with console logging
|
|
316
|
+
console.log('Session data saved - future apps will detect existing account');
|
|
317
|
+
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.error('Failed to save session data:', error);
|
|
320
|
+
}
|
|
321
|
+
|
|
282
322
|
// Simulate training progress over 10 seconds
|
|
283
323
|
let progress = 0;
|
|
284
324
|
const interval = setInterval(() => {
|
|
@@ -296,10 +336,11 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
296
336
|
platformToggles,
|
|
297
337
|
selectedTier,
|
|
298
338
|
tierData: requestData?.[selectedTier],
|
|
339
|
+
sessionSaved: true, // Indicate that session was saved
|
|
299
340
|
});
|
|
300
341
|
}
|
|
301
342
|
}, 1000); // Update every 1 second
|
|
302
|
-
}, [connections, onComplete, selectedTier, requestData, platformToggles]);
|
|
343
|
+
}, [connections, onComplete, selectedTier, requestData, platformToggles, username, AppName]);
|
|
303
344
|
|
|
304
345
|
const canProceedToPin = useCallback(() => {
|
|
305
346
|
// Check if at least one platform is toggled on
|
|
@@ -307,9 +348,14 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
307
348
|
}, [platformToggles]);
|
|
308
349
|
|
|
309
350
|
const handleProceed = () => {
|
|
310
|
-
|
|
351
|
+
console.log('Proceeding to next step');
|
|
352
|
+
// Show success screen first
|
|
353
|
+
setStep('success');
|
|
354
|
+
|
|
355
|
+
// After a delay, proceed to PIN
|
|
356
|
+
setTimeout(() => {
|
|
311
357
|
setStep('pin');
|
|
312
|
-
}
|
|
358
|
+
}, 3000);
|
|
313
359
|
};
|
|
314
360
|
|
|
315
361
|
return (
|
|
@@ -351,6 +397,14 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
351
397
|
<Text style={styles.onairosIconText}>O</Text>
|
|
352
398
|
</View>
|
|
353
399
|
</View>
|
|
400
|
+
|
|
401
|
+
{/* Already have an account button */}
|
|
402
|
+
<TouchableOpacity
|
|
403
|
+
style={styles.alreadyHaveAccountButton}
|
|
404
|
+
onPress={handleAlreadyHaveAccount}
|
|
405
|
+
>
|
|
406
|
+
<Text style={styles.alreadyHaveAccountText}>Already have an account?</Text>
|
|
407
|
+
</TouchableOpacity>
|
|
354
408
|
</View>
|
|
355
409
|
|
|
356
410
|
<ScrollView
|
|
@@ -375,7 +429,12 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
375
429
|
{/* Platform connection options */}
|
|
376
430
|
<View style={styles.platformsContainer}>
|
|
377
431
|
{platforms.map((platform) => (
|
|
378
|
-
<
|
|
432
|
+
<TouchableOpacity
|
|
433
|
+
key={platform.id}
|
|
434
|
+
style={styles.platformItem}
|
|
435
|
+
onPress={() => togglePlatform(platform.id)}
|
|
436
|
+
disabled={isConnectingPlatform}
|
|
437
|
+
>
|
|
379
438
|
<View style={styles.platformInfo}>
|
|
380
439
|
<Image
|
|
381
440
|
source={platform.icon}
|
|
@@ -386,13 +445,20 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
386
445
|
{platform.name}
|
|
387
446
|
</Text>
|
|
388
447
|
</View>
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
448
|
+
|
|
449
|
+
{isConnectingPlatform && currentPlatform === platform.id ? (
|
|
450
|
+
<ActivityIndicator size="small" color={COLORS.primary} />
|
|
451
|
+
) : (
|
|
452
|
+
<View style={[
|
|
453
|
+
styles.platformToggle,
|
|
454
|
+
platformToggles[platform.id] && styles.platformToggleActive
|
|
455
|
+
]}>
|
|
456
|
+
{platformToggles[platform.id] && (
|
|
457
|
+
<Icon name="check" size={16} color="#fff" />
|
|
458
|
+
)}
|
|
459
|
+
</View>
|
|
460
|
+
)}
|
|
461
|
+
</TouchableOpacity>
|
|
396
462
|
))}
|
|
397
463
|
</View>
|
|
398
464
|
</ScrollView>
|
|
@@ -419,6 +485,36 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
419
485
|
</>
|
|
420
486
|
)}
|
|
421
487
|
|
|
488
|
+
{step === 'success' && (
|
|
489
|
+
<View style={styles.successContainer}>
|
|
490
|
+
<View style={styles.successContent}>
|
|
491
|
+
{/* Big green checkmark */}
|
|
492
|
+
<View style={styles.successIcon}>
|
|
493
|
+
<Icon name="check" size={48} color="#fff" />
|
|
494
|
+
</View>
|
|
495
|
+
|
|
496
|
+
<Text style={styles.successTitle}>Never Connect Again!</Text>
|
|
497
|
+
<Text style={styles.successSubtitle}>
|
|
498
|
+
Your login session has been saved
|
|
499
|
+
</Text>
|
|
500
|
+
|
|
501
|
+
<View style={styles.successMessage}>
|
|
502
|
+
<Text style={styles.successMessageText}>
|
|
503
|
+
Your Onairos account and platform connections are now saved in your browser cookies.
|
|
504
|
+
Next time you use any app with Onairos, you'll be automatically signed in without
|
|
505
|
+
needing to reconnect your accounts.
|
|
506
|
+
</Text>
|
|
507
|
+
</View>
|
|
508
|
+
|
|
509
|
+
{/* Auto-progress indicator */}
|
|
510
|
+
<View style={styles.progressIndicator}>
|
|
511
|
+
<ActivityIndicator size="small" color="#4CAF50" />
|
|
512
|
+
<Text style={styles.progressText}>Continuing...</Text>
|
|
513
|
+
</View>
|
|
514
|
+
</View>
|
|
515
|
+
</View>
|
|
516
|
+
)}
|
|
517
|
+
|
|
422
518
|
{step === 'pin' && (
|
|
423
519
|
<PinInput
|
|
424
520
|
onSubmit={handlePinSubmit}
|
|
@@ -461,6 +557,17 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
461
557
|
onComplete={() => setStep('connect')}
|
|
462
558
|
/>
|
|
463
559
|
)}
|
|
560
|
+
|
|
561
|
+
{/* Login WebView for existing account check */}
|
|
562
|
+
{showLoginWebView && (
|
|
563
|
+
<OAuthWebView
|
|
564
|
+
url="https://onairos.uk/signin"
|
|
565
|
+
platform="onairos"
|
|
566
|
+
onClose={() => setShowLoginWebView(false)}
|
|
567
|
+
onSuccess={handleLoginWebViewComplete}
|
|
568
|
+
onComplete={handleLoginWebViewComplete}
|
|
569
|
+
/>
|
|
570
|
+
)}
|
|
464
571
|
</SafeAreaView>
|
|
465
572
|
</Animated.View>
|
|
466
573
|
</TouchableWithoutFeedback>
|
|
@@ -539,20 +646,20 @@ const styles = StyleSheet.create({
|
|
|
539
646
|
color: '#000',
|
|
540
647
|
},
|
|
541
648
|
titleContainer: {
|
|
542
|
-
marginBottom:
|
|
649
|
+
marginBottom: 20,
|
|
543
650
|
},
|
|
544
651
|
mainTitle: {
|
|
545
|
-
fontSize:
|
|
652
|
+
fontSize: 20,
|
|
546
653
|
fontWeight: '600',
|
|
547
654
|
color: '#000',
|
|
548
655
|
textAlign: 'center',
|
|
549
|
-
marginBottom:
|
|
656
|
+
marginBottom: 12,
|
|
550
657
|
},
|
|
551
658
|
privacyMessage: {
|
|
552
659
|
fontSize: 14,
|
|
553
660
|
color: '#666',
|
|
554
661
|
textAlign: 'center',
|
|
555
|
-
marginBottom:
|
|
662
|
+
marginBottom: 12,
|
|
556
663
|
},
|
|
557
664
|
content: {
|
|
558
665
|
flex: 1,
|
|
@@ -560,8 +667,7 @@ const styles = StyleSheet.create({
|
|
|
560
667
|
},
|
|
561
668
|
scrollContent: {
|
|
562
669
|
flexGrow: 1,
|
|
563
|
-
paddingBottom:
|
|
564
|
-
minHeight: '100%',
|
|
670
|
+
paddingBottom: 20,
|
|
565
671
|
},
|
|
566
672
|
platformsContainer: {
|
|
567
673
|
marginTop: 16,
|
|
@@ -570,20 +676,21 @@ const styles = StyleSheet.create({
|
|
|
570
676
|
flexDirection: 'row',
|
|
571
677
|
justifyContent: 'space-between',
|
|
572
678
|
alignItems: 'center',
|
|
573
|
-
padding:
|
|
679
|
+
padding: 12,
|
|
574
680
|
backgroundColor: '#fff',
|
|
575
|
-
borderRadius:
|
|
576
|
-
marginBottom:
|
|
681
|
+
borderRadius: 12,
|
|
682
|
+
marginBottom: 8,
|
|
577
683
|
borderWidth: 1,
|
|
578
684
|
borderColor: '#eee',
|
|
579
685
|
},
|
|
580
686
|
platformInfo: {
|
|
581
687
|
flexDirection: 'row',
|
|
582
688
|
alignItems: 'center',
|
|
689
|
+
flex: 1,
|
|
583
690
|
},
|
|
584
691
|
platformIcon: {
|
|
585
|
-
width:
|
|
586
|
-
height:
|
|
692
|
+
width: 24,
|
|
693
|
+
height: 24,
|
|
587
694
|
marginRight: 12,
|
|
588
695
|
},
|
|
589
696
|
platformName: {
|
|
@@ -624,4 +731,88 @@ const styles = StyleSheet.create({
|
|
|
624
731
|
fontSize: 16,
|
|
625
732
|
fontWeight: '600',
|
|
626
733
|
},
|
|
734
|
+
alreadyHaveAccountButton: {
|
|
735
|
+
paddingVertical: 8,
|
|
736
|
+
paddingHorizontal: 16,
|
|
737
|
+
},
|
|
738
|
+
alreadyHaveAccountText: {
|
|
739
|
+
color: '#666',
|
|
740
|
+
fontSize: 16,
|
|
741
|
+
},
|
|
742
|
+
successContainer: {
|
|
743
|
+
flex: 1,
|
|
744
|
+
justifyContent: 'center',
|
|
745
|
+
alignItems: 'center',
|
|
746
|
+
},
|
|
747
|
+
successContent: {
|
|
748
|
+
backgroundColor: '#fff',
|
|
749
|
+
padding: 24,
|
|
750
|
+
borderRadius: 16,
|
|
751
|
+
alignItems: 'center',
|
|
752
|
+
},
|
|
753
|
+
successIcon: {
|
|
754
|
+
backgroundColor: '#4CAF50',
|
|
755
|
+
borderRadius: 24,
|
|
756
|
+
padding: 12,
|
|
757
|
+
marginBottom: 16,
|
|
758
|
+
},
|
|
759
|
+
successTitle: {
|
|
760
|
+
fontSize: 22,
|
|
761
|
+
fontWeight: '600',
|
|
762
|
+
color: '#000',
|
|
763
|
+
textAlign: 'center',
|
|
764
|
+
marginBottom: 16,
|
|
765
|
+
},
|
|
766
|
+
successSubtitle: {
|
|
767
|
+
fontSize: 14,
|
|
768
|
+
color: '#666',
|
|
769
|
+
textAlign: 'center',
|
|
770
|
+
marginBottom: 16,
|
|
771
|
+
},
|
|
772
|
+
successMessage: {
|
|
773
|
+
backgroundColor: '#f0f0f0',
|
|
774
|
+
padding: 16,
|
|
775
|
+
borderRadius: 8,
|
|
776
|
+
marginBottom: 16,
|
|
777
|
+
},
|
|
778
|
+
successMessageText: {
|
|
779
|
+
fontSize: 14,
|
|
780
|
+
color: '#666',
|
|
781
|
+
},
|
|
782
|
+
platformToggle: {
|
|
783
|
+
width: 24,
|
|
784
|
+
height: 24,
|
|
785
|
+
borderRadius: 12,
|
|
786
|
+
borderWidth: 1,
|
|
787
|
+
borderColor: '#ccc',
|
|
788
|
+
alignItems: 'center',
|
|
789
|
+
justifyContent: 'center',
|
|
790
|
+
backgroundColor: '#fff',
|
|
791
|
+
},
|
|
792
|
+
platformToggleActive: {
|
|
793
|
+
borderColor: '#000',
|
|
794
|
+
backgroundColor: '#000',
|
|
795
|
+
},
|
|
796
|
+
// Dark mode styles
|
|
797
|
+
darkPlatformItem: {
|
|
798
|
+
backgroundColor: '#333',
|
|
799
|
+
borderColor: '#555',
|
|
800
|
+
},
|
|
801
|
+
darkText: {
|
|
802
|
+
color: '#fff',
|
|
803
|
+
},
|
|
804
|
+
darkSubText: {
|
|
805
|
+
color: '#ccc',
|
|
806
|
+
},
|
|
807
|
+
progressIndicator: {
|
|
808
|
+
flexDirection: 'row',
|
|
809
|
+
alignItems: 'center',
|
|
810
|
+
marginTop: 16,
|
|
811
|
+
},
|
|
812
|
+
progressText: {
|
|
813
|
+
fontSize: 16,
|
|
814
|
+
fontWeight: '500',
|
|
815
|
+
color: '#000',
|
|
816
|
+
marginLeft: 8,
|
|
817
|
+
},
|
|
627
818
|
});
|
|
@@ -71,6 +71,11 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
71
71
|
const handleNavigationStateChange = (navState: any) => {
|
|
72
72
|
console.log(`Navigation state changed for ${platform}:`, navState.url);
|
|
73
73
|
|
|
74
|
+
// Don't process navigation changes while still loading the initial page
|
|
75
|
+
if (isLoading) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
// Check for error states first
|
|
75
80
|
if (navState.url.includes('error=') || navState.url.includes('access_denied')) {
|
|
76
81
|
console.log('OAuth error detected:', navState.url);
|
|
@@ -78,138 +83,71 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
78
83
|
return;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
navState.url.includes('onairos.uk/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// Enhanced platform-specific success patterns
|
|
91
|
-
const platformSuccessPatterns: Record<string, RegExp[]> = {
|
|
92
|
-
reddit: [
|
|
93
|
-
/reddit\.com\/api\/v1\/authorize\?done=true/,
|
|
94
|
-
/reddit\.com\/api\/v1\/authorize\/success/,
|
|
95
|
-
/reddit\.com.*code=/
|
|
96
|
-
],
|
|
97
|
-
pinterest: [
|
|
98
|
-
/pinterest\.com\/oauth\/success/,
|
|
99
|
-
/pinterest\.com\/oauth\/complete/,
|
|
100
|
-
/pinterest\.com.*code=/,
|
|
101
|
-
/api2\.onairos\.uk\/pinterest\/callback/,
|
|
102
|
-
/onairos\.uk.*pinterest/
|
|
103
|
-
],
|
|
104
|
-
linkedin: [
|
|
105
|
-
/linkedin\.com\/oauth\/success/,
|
|
106
|
-
/linkedin\.com\/oauth\/complete/,
|
|
107
|
-
/linkedin\.com\/uas\/oauth2\/authorization\/success/,
|
|
108
|
-
/linkedin\.com.*code=/
|
|
109
|
-
],
|
|
110
|
-
email: [/success/, /complete/],
|
|
111
|
-
instagram: [
|
|
112
|
-
/instagram\.com\/oauth\/authorize\?done=true/,
|
|
113
|
-
/instagram\.com\/oauth\/success/,
|
|
114
|
-
/instagram\.com.*code=/,
|
|
115
|
-
/api2\.onairos\.uk\/instagram\/callback/,
|
|
116
|
-
/onairos\.uk.*instagram/
|
|
117
|
-
],
|
|
118
|
-
youtube: [
|
|
119
|
-
/accounts\.google\.com\/o\/oauth2\/approval/,
|
|
120
|
-
/youtube\.com\/oauth\/success/,
|
|
121
|
-
/accounts\.google\.com.*code=/,
|
|
122
|
-
/api2\.onairos\.uk\/youtube\/callback/
|
|
123
|
-
]
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// Check for platform-specific success patterns
|
|
127
|
-
const isPlatformSuccess = platform && platformSuccessPatterns[platform] ?
|
|
128
|
-
platformSuccessPatterns[platform].some(pattern => pattern.test(navState.url)) :
|
|
129
|
-
false;
|
|
130
|
-
|
|
131
|
-
// Check for callback URLs that might contain the authorization code
|
|
132
|
-
const isCallbackUrl = (
|
|
133
|
-
navState.url.includes('/callback') ||
|
|
134
|
-
navState.url.includes('code=') ||
|
|
135
|
-
navState.url.includes('token=') ||
|
|
136
|
-
navState.url.includes('access_token=') ||
|
|
137
|
-
navState.url.includes('api2.onairos.uk') ||
|
|
138
|
-
navState.url.includes('oauth_token=')
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
// Extract authorization code or token if present
|
|
142
|
-
let authCode = null;
|
|
143
|
-
if (isCallbackUrl) {
|
|
144
|
-
console.log('Detected callback URL with possible code/token');
|
|
145
|
-
|
|
146
|
-
// Try to extract code or token using different patterns
|
|
147
|
-
const codeMatch = navState.url.match(/code=([^&]+)/);
|
|
148
|
-
const tokenMatch = navState.url.match(/(?:token|access_token)=([^&]+)/);
|
|
149
|
-
const oauthTokenMatch = navState.url.match(/oauth_token=([^&]+)/);
|
|
150
|
-
|
|
151
|
-
if (codeMatch && codeMatch[1]) {
|
|
152
|
-
authCode = decodeURIComponent(codeMatch[1]);
|
|
153
|
-
console.log('OAuth code extracted:', authCode);
|
|
154
|
-
} else if (tokenMatch && tokenMatch[1]) {
|
|
155
|
-
authCode = decodeURIComponent(tokenMatch[1]);
|
|
156
|
-
console.log('OAuth token extracted:', authCode);
|
|
157
|
-
} else if (oauthTokenMatch && oauthTokenMatch[1]) {
|
|
158
|
-
authCode = decodeURIComponent(oauthTokenMatch[1]);
|
|
159
|
-
console.log('OAuth token extracted:', authCode);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Call onSuccess with the extracted code/token
|
|
163
|
-
if (authCode) {
|
|
164
|
-
console.log(`Calling onSuccess for ${platform} with code:`, authCode);
|
|
86
|
+
// Special handling for Onairos login page (existing account check)
|
|
87
|
+
if (platform === 'onairos') {
|
|
88
|
+
// Check if user successfully logged in to Onairos
|
|
89
|
+
if (navState.url.includes('onairos.uk/Home') ||
|
|
90
|
+
navState.url.includes('onairos.uk/dashboard') ||
|
|
91
|
+
navState.url.includes('onairos.uk/profile')) {
|
|
92
|
+
console.log('Onairos login successful - existing account detected');
|
|
165
93
|
|
|
166
|
-
// Clear timeout since
|
|
94
|
+
// Clear timeout since login completed successfully
|
|
167
95
|
if (timeoutRef.current) {
|
|
168
96
|
clearTimeout(timeoutRef.current);
|
|
169
97
|
}
|
|
170
98
|
|
|
171
|
-
onSuccess(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}, 1000);
|
|
99
|
+
onSuccess('onairos_login_success');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// If still on login page, don't close
|
|
104
|
+
if (navState.url.includes('onairos.uk/signin') ||
|
|
105
|
+
navState.url.includes('onairos.uk/login')) {
|
|
106
|
+
console.log('Still on Onairos login page, waiting for user to complete login');
|
|
180
107
|
return;
|
|
181
108
|
}
|
|
182
109
|
}
|
|
183
110
|
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
111
|
+
// For platform OAuth flows, only close when we get the FINAL redirect from Onairos backend
|
|
112
|
+
// This happens AFTER the user has logged in and the backend has processed the OAuth callback
|
|
113
|
+
const isFinalOAuthRedirect = (
|
|
114
|
+
navState.url.includes('onairos.uk/Home') ||
|
|
115
|
+
navState.url.includes('onairos.uk/home') ||
|
|
116
|
+
navState.url.includes('onairos.uk/success') ||
|
|
117
|
+
navState.url.includes('onairos.uk/dashboard') ||
|
|
118
|
+
(navState.url.includes('onairos.uk') && navState.url.includes('complete'))
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Only close when we get the final redirect from Onairos backend
|
|
122
|
+
if (isFinalOAuthRedirect) {
|
|
123
|
+
console.log(`Final OAuth redirect detected for ${platform} - user has completed login`);
|
|
187
124
|
|
|
188
|
-
//
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
onSuccess('success');
|
|
125
|
+
// Clear timeout since OAuth completed successfully
|
|
126
|
+
if (timeoutRef.current) {
|
|
127
|
+
clearTimeout(timeoutRef.current);
|
|
192
128
|
}
|
|
193
129
|
|
|
194
|
-
|
|
195
|
-
if (onComplete) {
|
|
196
|
-
console.log('Calling onComplete to close OAuth window');
|
|
197
|
-
onComplete();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Handle specific redirect patterns that indicate completion
|
|
202
|
-
if (navState.url.includes('api2.onairos.uk') &&
|
|
203
|
-
(navState.url.includes('callback') || navState.url.includes('success'))) {
|
|
204
|
-
console.log(`Backend callback detected for ${platform}`);
|
|
205
|
-
onSuccess('backend_callback_success');
|
|
130
|
+
onSuccess('oauth_complete');
|
|
206
131
|
|
|
132
|
+
// Close the OAuth window after a short delay
|
|
207
133
|
setTimeout(() => {
|
|
208
134
|
if (onComplete) {
|
|
135
|
+
console.log('Calling onComplete to close OAuth window');
|
|
209
136
|
onComplete();
|
|
210
137
|
}
|
|
211
138
|
}, 1500);
|
|
139
|
+
return;
|
|
212
140
|
}
|
|
141
|
+
|
|
142
|
+
// Log intermediate steps but don't close the WebView
|
|
143
|
+
if (navState.url.includes('/callback') || navState.url.includes('code=')) {
|
|
144
|
+
console.log(`OAuth callback detected for ${platform}, but waiting for final redirect from Onairos backend`);
|
|
145
|
+
// Don't close here - wait for the final redirect
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Log other navigation for debugging
|
|
150
|
+
console.log(`${platform} OAuth navigation:`, navState.url);
|
|
213
151
|
};
|
|
214
152
|
|
|
215
153
|
const handleLoadEnd = () => {
|