@onairos/react-native 3.0.25 → 3.0.27

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.
Files changed (33) hide show
  1. package/lib/commonjs/components/TrainingModal.js +16 -120
  2. package/lib/commonjs/components/TrainingModal.js.map +1 -1
  3. package/lib/commonjs/components/UniversalOnboarding.js +42 -83
  4. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  5. package/lib/commonjs/components/onboarding/OAuthWebView.js +49 -124
  6. package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
  7. package/lib/commonjs/constants/index.js +3 -3
  8. package/lib/commonjs/constants/index.js.map +1 -1
  9. package/lib/commonjs/services/platformAuthService.js +81 -95
  10. package/lib/commonjs/services/platformAuthService.js.map +1 -1
  11. package/lib/module/components/TrainingModal.js +17 -120
  12. package/lib/module/components/TrainingModal.js.map +1 -1
  13. package/lib/module/components/UniversalOnboarding.js +43 -84
  14. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  15. package/lib/module/components/onboarding/OAuthWebView.js +50 -125
  16. package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
  17. package/lib/module/constants/index.js +3 -3
  18. package/lib/module/constants/index.js.map +1 -1
  19. package/lib/module/index.js +9 -10
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/services/platformAuthService.js +80 -93
  22. package/lib/module/services/platformAuthService.js.map +1 -1
  23. package/lib/typescript/components/TrainingModal.d.ts.map +1 -1
  24. package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
  25. package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
  26. package/lib/typescript/services/platformAuthService.d.ts +5 -11
  27. package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/TrainingModal.tsx +61 -202
  30. package/src/components/UniversalOnboarding.tsx +42 -83
  31. package/src/components/onboarding/OAuthWebView.tsx +59 -121
  32. package/src/constants/index.ts +3 -3
  33. package/src/services/platformAuthService.ts +80 -110
@@ -52,9 +52,8 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
52
52
  const [platformToggles, setPlatformToggles] = useState<{[key: string]: boolean}>({});
53
53
  const [oauthUrl, setOauthUrl] = useState<string>('');
54
54
  const [currentPlatform, setCurrentPlatform] = useState<string>('');
55
- const [userEmail, setUserEmail] = useState<string>('user@example.com'); // Use proper email instead of random username
55
+ const [username, setUsername] = useState<string>('Avatar');
56
56
  const [isConnectingPlatform, setIsConnectingPlatform] = useState<boolean>(false);
57
- const [connectingPlatform, setConnectingPlatform] = useState<string | null>(null);
58
57
 
59
58
  const platforms = [
60
59
  { id: 'instagram', name: 'Instagram', icon: require('../assets/images/instagram.png') },
@@ -161,7 +160,6 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
161
160
  // Attempt to connect platform
162
161
  try {
163
162
  setIsConnectingPlatform(true);
164
- setConnectingPlatform(platformId);
165
163
  console.log(`Initiating connection for ${platformId}`);
166
164
 
167
165
  // Check if platform has a native SDK
@@ -180,13 +178,13 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
180
178
  // Update connections state
181
179
  setConnections(prev => ({
182
180
  ...prev,
183
- [platformId]: { userName: userEmail, connected: true }
181
+ [platformId]: { userName: username, connected: true }
184
182
  }));
185
183
  }
186
184
  } else {
187
185
  console.log(`Initiating OAuth flow for ${platformId}`);
188
186
  // Use OAuth flow through proxy server
189
- const oauthUrl = await initiateOAuth(platformId, userEmail);
187
+ const oauthUrl = await initiateOAuth(platformId, username, AppName);
190
188
  if (oauthUrl) {
191
189
  console.log(`Received OAuth URL for ${platformId}: ${oauthUrl}`);
192
190
  setCurrentPlatform(platformId);
@@ -198,14 +196,8 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
198
196
  }
199
197
  } catch (error) {
200
198
  console.error(`Error connecting ${platformId}:`, error);
201
- // Reset toggle state on error
202
- setPlatformToggles(prev => ({
203
- ...prev,
204
- [platformId]: false
205
- }));
206
199
  } finally {
207
200
  setIsConnectingPlatform(false);
208
- setConnectingPlatform(null);
209
201
  }
210
202
  } else {
211
203
  // Disconnect platform
@@ -222,7 +214,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
222
214
  return newConnections;
223
215
  });
224
216
  }
225
- }, [platformToggles, userEmail]);
217
+ }, [platformToggles, username]);
226
218
 
227
219
  /**
228
220
  * Handles OAuth callback URLs
@@ -238,7 +230,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
238
230
  // Update connections state
239
231
  setConnections(prev => ({
240
232
  ...prev,
241
- [platform]: { userName: userEmail, connected: true }
233
+ [platform]: { userName: username, connected: true }
242
234
  }));
243
235
 
244
236
  // Update platform toggles
@@ -253,7 +245,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
253
245
  } catch (error) {
254
246
  console.error('Error handling OAuth callback:', error);
255
247
  }
256
- }, [currentPlatform, userEmail]);
248
+ }, [currentPlatform, username]);
257
249
 
258
250
  /**
259
251
  * Handles completion of the OAuth flow
@@ -261,13 +253,13 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
261
253
  const handleOAuthSuccess = useCallback((code: string) => {
262
254
  console.log(`OAuth success for ${currentPlatform} with code: ${code}`);
263
255
 
264
- // Update connections for the current platform
265
- if (currentPlatform) {
266
- // Update connections state
267
- setConnections(prev => ({
268
- ...prev,
269
- [currentPlatform]: { userName: userEmail, connected: true }
270
- }));
256
+ // Update connections for the current platform
257
+ if (currentPlatform) {
258
+ // Update connections state
259
+ setConnections(prev => ({
260
+ ...prev,
261
+ [currentPlatform]: { userName: username, connected: true }
262
+ }));
271
263
 
272
264
  // Update platform toggles
273
265
  setPlatformToggles(prev => ({
@@ -275,20 +267,14 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
275
267
  [currentPlatform]: true
276
268
  }));
277
269
 
278
- // In a real implementation, we would send the code to our server
279
- // to exchange it for an access token and store it securely
280
- console.log(`Simulating token exchange for ${currentPlatform}`);
281
-
282
- // For demo purposes, we'll just simulate a successful token exchange
283
- if (debug || test) {
284
- console.log('Debug mode: Simulating successful token exchange');
285
- }
270
+ console.log(`Successfully connected ${currentPlatform} for user ${username}`);
286
271
  }
287
272
 
288
273
  // Close OAuth window and return to connect step
289
274
  setOauthUrl('');
275
+ setCurrentPlatform('');
290
276
  setStep('connect');
291
- }, [currentPlatform, userEmail, debug, test]);
277
+ }, [currentPlatform, username]);
292
278
 
293
279
  const handlePinSubmit = useCallback(async (userPin: string) => {
294
280
  setPin(userPin);
@@ -296,16 +282,23 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
296
282
  // Simulate training progress over 10 seconds
297
283
  let progress = 0;
298
284
  const interval = setInterval(() => {
299
- progress += 1; // 10% progress every second for 1 seconds total
285
+ progress += 0.1; // 10% every second for 10 seconds total
300
286
  setTraining({
301
287
  progress,
302
288
  eta: `${Math.round((1 - progress) * 10)} seconds remaining`,
303
289
  });
304
290
  if (progress >= 1) {
305
291
  clearInterval(interval);
306
- // Training complete - TrainingModal will handle email input and final completion
292
+ // Close overlay and call the original onResolved callback
293
+ onComplete('https://api2.onairos.uk', 'dummy-token', {
294
+ pin: userPin,
295
+ connections,
296
+ platformToggles,
297
+ selectedTier,
298
+ tierData: requestData?.[selectedTier],
299
+ });
307
300
  }
308
- }, 1000); // 1 second intervals for 10 total seconds
301
+ }, 1000); // Update every 1 second
309
302
  }, [connections, onComplete, selectedTier, requestData, platformToggles]);
310
303
 
311
304
  const canProceedToPin = useCallback(() => {
@@ -373,41 +366,26 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
373
366
 
374
367
  {/* Platform connection options */}
375
368
  <View style={styles.platformsContainer}>
376
- {platforms.map((platform) => (
377
- <View key={platform.id} style={[
378
- styles.platformItem,
379
- connections[platform.id]?.connected && styles.platformItemConnected
380
- ]}>
381
- <View style={styles.platformInfo}>
382
- <Image
383
- source={platform.icon}
384
- style={styles.platformIcon}
385
- resizeMode="contain"
386
- />
387
- <View style={styles.platformTextContainer}>
369
+ {platforms.map((platform) => (
370
+ <View key={platform.id} style={styles.platformItem}>
371
+ <View style={styles.platformInfo}>
372
+ <Image
373
+ source={platform.icon}
374
+ style={styles.platformIcon}
375
+ resizeMode="contain"
376
+ />
388
377
  <Text style={styles.platformName}>
389
378
  {platform.name}
390
379
  </Text>
391
- {connections[platform.id]?.connected && (
392
- <Text style={styles.connectedText}>Connected</Text>
393
- )}
394
380
  </View>
381
+ <Switch
382
+ value={platformToggles[platform.id]}
383
+ onValueChange={() => togglePlatform(platform.id)}
384
+ trackColor={{ false: '#767577', true: '#81b0ff' }}
385
+ thumbColor={platformToggles[platform.id] ? '#2196F3' : '#f4f3f4'}
386
+ />
395
387
  </View>
396
- <View style={styles.platformActions}>
397
- {connectingPlatform === platform.id ? (
398
- <ActivityIndicator size="small" color={COLORS.primary} />
399
- ) : (
400
- <Switch
401
- value={platformToggles[platform.id] || connections[platform.id]?.connected || false}
402
- onValueChange={() => togglePlatform(platform.id)}
403
- trackColor={{ false: '#767577', true: '#81b0ff' }}
404
- thumbColor={platformToggles[platform.id] || connections[platform.id]?.connected ? '#2196F3' : '#f4f3f4'}
405
- disabled={connectingPlatform !== null}
406
- />
407
- )}
408
- </View>
409
- </View>
410
- ))}
388
+ ))}
411
389
  </View>
412
390
  </ScrollView>
413
391
 
@@ -456,11 +434,10 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
456
434
  platformToggles,
457
435
  selectedTier,
458
436
  tierData: requestData?.[selectedTier],
459
- userEmail,
460
437
  });
461
438
  }}
462
439
  modelKey="onairosTrainingModel"
463
- username={userEmail}
440
+ username={username}
464
441
  />
465
442
  )}
466
443
 
@@ -601,24 +578,6 @@ const styles = StyleSheet.create({
601
578
  fontWeight: '500',
602
579
  color: '#000',
603
580
  },
604
- platformTextContainer: {
605
- flex: 1,
606
- },
607
- connectedText: {
608
- fontSize: 12,
609
- color: '#4CAF50',
610
- fontWeight: '500',
611
- marginTop: 2,
612
- },
613
- platformActions: {
614
- alignItems: 'center',
615
- justifyContent: 'center',
616
- },
617
- platformItemConnected: {
618
- backgroundColor: '#F8F9FA',
619
- borderColor: '#4CAF50',
620
- borderWidth: 1,
621
- },
622
581
  footer: {
623
582
  flexDirection: 'row',
624
583
  alignItems: 'center',
@@ -1,9 +1,8 @@
1
1
  import React, { useCallback, useState } from 'react';
2
- import { View, StyleSheet, ActivityIndicator, SafeAreaView, TouchableOpacity, Text } from 'react-native';
2
+ import { View, StyleSheet, ActivityIndicator, SafeAreaView, TouchableOpacity } from 'react-native';
3
3
  import { WebView, WebViewNavigation } from 'react-native-webview';
4
4
  import Icon from 'react-native-vector-icons/MaterialIcons';
5
5
  import { COLORS } from '../../constants';
6
- import { isOAuthSuccess, handleOAuthCallback } from '../../services/platformAuthService';
7
6
  import type { OAuthWebViewProps } from '../../types';
8
7
 
9
8
  export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
@@ -14,56 +13,47 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
14
13
  onSuccess,
15
14
  }) => {
16
15
  const [loading, setLoading] = useState(true);
17
- const [currentUrl, setCurrentUrl] = useState(url);
18
16
 
19
17
  const handleNavigationStateChange = useCallback(
20
18
  (navState: WebViewNavigation) => {
21
- console.log(`[OAuthWebView] Navigation state changed for ${platform}:`, navState.url);
22
- setCurrentUrl(navState.url);
19
+ console.log('Navigation state changed:', navState.url);
23
20
 
24
- // Check for final redirect to onairos.uk/Home (indicates proxy has processed the callback)
25
- if (navState.url.includes('onairos.uk/Home')) {
26
- console.log(`[OAuthWebView] Detected final redirect to onairos.uk/Home for ${platform}`);
27
-
28
- // Add a small delay to ensure the redirect is fully processed
29
- setTimeout(() => {
30
- onSuccess('success');
31
- if (onComplete) {
32
- onComplete();
33
- }
34
- }, 500);
35
- return;
36
- }
21
+ // Check for the final redirect to onairos.uk/Home
22
+ const isFinalRedirect = navState.url.includes('onairos.uk/Home');
37
23
 
38
- // Check for platform-specific success patterns using the service
39
- if (platform && isOAuthSuccess(navState.url, platform)) {
40
- console.log(`[OAuthWebView] Detected platform-specific success pattern for ${platform}`);
41
-
42
- // For YouTube/Google, wait for the final redirect
43
- if (platform === 'youtube') {
44
- console.log(`[OAuthWebView] YouTube success detected, waiting for final redirect...`);
45
- // Don't close immediately for YouTube, wait for the onairos.uk/Home redirect
46
- return;
47
- }
48
-
49
- // For other platforms, close immediately
50
- setTimeout(() => {
51
- onSuccess('success');
52
- if (onComplete) {
53
- onComplete();
54
- }
55
- }, 300);
56
- return;
57
- }
24
+ // Check for Instagram-specific success patterns
25
+ const isInstagramSuccess = (
26
+ platform === 'instagram' &&
27
+ (navState.url.includes('instagram.com/oauth/authorize') ||
28
+ navState.url.includes('instagram.com/accounts/login') ||
29
+ navState.url.includes('code='))
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
+ );
58
42
 
59
43
  // Check for callback URLs with authorization codes
60
- if (navState.url.includes('/callback') || navState.url.includes('code=')) {
61
- console.log(`[OAuthWebView] Detected callback URL for ${platform}:`, navState.url);
62
-
44
+ const isCallbackUrl = navState.url.includes('/callback') || navState.url.includes('code=');
45
+
46
+ // If we detect success, close the window and update connection status
47
+ if (isFinalRedirect || isInstagramSuccess || isYouTubeSuccess || isLinkedInSuccess) {
48
+ onSuccess('success');
49
+ if (onComplete) {
50
+ onComplete();
51
+ }
52
+ return;
53
+ } else if (isCallbackUrl) {
63
54
  // Extract the authorization code
64
- const authCode = handleOAuthCallback(navState.url);
55
+ const authCode = extractAuthCode(navState.url);
65
56
  if (authCode) {
66
- console.log(`[OAuthWebView] Extracted auth code for ${platform}:`, authCode);
67
57
  onSuccess(authCode);
68
58
  if (onComplete) {
69
59
  onComplete();
@@ -75,22 +65,27 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
75
65
  [platform, onComplete, onSuccess]
76
66
  );
77
67
 
78
- const handleLoadStart = useCallback(() => {
79
- setLoading(true);
80
- }, []);
81
-
82
68
  const handleLoadEnd = useCallback(() => {
83
69
  setLoading(false);
84
70
  }, []);
85
71
 
86
- const handleError = useCallback((syntheticEvent: any) => {
87
- const { nativeEvent } = syntheticEvent;
88
- console.error(`[OAuthWebView] WebView error for ${platform}:`, nativeEvent);
89
- setLoading(false);
90
- }, [platform]);
91
-
92
- // Get iOS Safari user agent for better compatibility
93
- const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1';
72
+ // Extract auth code from redirect URL
73
+ const extractAuthCode = (redirectUrl: string): string => {
74
+ try {
75
+ // First try to extract code from URL parameters
76
+ const codeMatch = redirectUrl.match(/code=([^&]+)/);
77
+ if (codeMatch && codeMatch[1]) {
78
+ return codeMatch[1];
79
+ }
80
+
81
+ // If that fails, try parsing as URL
82
+ const url = new URL(redirectUrl);
83
+ return url.searchParams.get('code') || '';
84
+ } catch (error) {
85
+ console.error('Error extracting auth code:', error);
86
+ return '';
87
+ }
88
+ };
94
89
 
95
90
  return (
96
91
  <SafeAreaView style={styles.container}>
@@ -104,56 +99,31 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
104
99
  size={20}
105
100
  color={getPlatformColor(platform || 'default')}
106
101
  />
107
- <Text style={styles.platformTitle}>
108
- Connect {platform ? platform.charAt(0).toUpperCase() + platform.slice(1) : 'Account'}
109
- </Text>
110
102
  </View>
111
- <View style={styles.placeholder} />
112
103
  </View>
113
104
 
114
105
  <WebView
115
106
  source={{ uri: url }}
116
107
  onNavigationStateChange={handleNavigationStateChange}
117
- onLoadStart={handleLoadStart}
118
108
  onLoadEnd={handleLoadEnd}
119
- onError={handleError}
120
109
  startInLoadingState={true}
121
110
  renderLoading={() => <View />}
122
111
  style={styles.webView}
123
- // Essential WebView configuration for OAuth
124
112
  javaScriptEnabled={true}
125
113
  domStorageEnabled={true}
126
- cacheEnabled={true}
127
- incognito={false} // Allow session persistence
128
- sharedCookiesEnabled={true} // Critical for Google/YouTube OAuth
129
- thirdPartyCookiesEnabled={true} // Required for OAuth flows
130
- userAgent={userAgent} // iOS Safari for better compatibility
131
- // Additional settings for better OAuth support
114
+ cacheEnabled={false}
115
+ incognito={false}
116
+ sharedCookiesEnabled={true}
117
+ thirdPartyCookiesEnabled={true}
132
118
  allowsInlineMediaPlayback={true}
133
119
  mediaPlaybackRequiresUserAction={false}
134
120
  allowsBackForwardNavigationGestures={true}
135
- // Security settings
136
- allowsLinkPreview={false}
137
- allowFileAccess={false}
138
- allowUniversalAccessFromFileURLs={false}
139
- mixedContentMode="compatibility"
121
+ 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"
140
122
  />
141
123
 
142
124
  {loading && (
143
125
  <View style={styles.loadingContainer}>
144
126
  <ActivityIndicator size="large" color={COLORS.primary} />
145
- <Text style={styles.loadingText}>
146
- Connecting to {platform ? platform.charAt(0).toUpperCase() + platform.slice(1) : 'platform'}...
147
- </Text>
148
- </View>
149
- )}
150
-
151
- {/* Debug info in development */}
152
- {__DEV__ && (
153
- <View style={styles.debugContainer}>
154
- <Text style={styles.debugText} numberOfLines={1}>
155
- {currentUrl}
156
- </Text>
157
127
  </View>
158
128
  )}
159
129
  </SafeAreaView>
@@ -173,8 +143,6 @@ const getPlatformIcon = (platform: string): string => {
173
143
  return 'push-pin';
174
144
  case 'reddit':
175
145
  return 'forum';
176
- case 'email':
177
- return 'email';
178
146
  default:
179
147
  return 'link';
180
148
  }
@@ -193,8 +161,6 @@ const getPlatformColor = (platform: string): string => {
193
161
  return '#E60023';
194
162
  case 'reddit':
195
163
  return '#FF4500';
196
- case 'email':
197
- return '#4285F4';
198
164
  default:
199
165
  return COLORS.primary;
200
166
  }
@@ -216,49 +182,21 @@ const styles = StyleSheet.create({
216
182
  },
217
183
  titleContainer: {
218
184
  flex: 1,
219
- flexDirection: 'row',
220
185
  alignItems: 'center',
221
- justifyContent: 'center',
222
- },
223
- platformTitle: {
224
- fontSize: 16,
225
- fontWeight: '600',
226
- color: '#000',
227
- marginLeft: 8,
228
186
  },
229
187
  closeButton: {
230
188
  padding: 8,
231
- width: 40,
232
- },
233
- placeholder: {
234
- width: 40,
189
+ position: 'absolute',
190
+ left: 16,
191
+ zIndex: 10,
235
192
  },
236
193
  webView: {
237
194
  flex: 1,
238
195
  },
239
196
  loadingContainer: {
240
197
  ...StyleSheet.absoluteFillObject,
241
- backgroundColor: 'rgba(255, 255, 255, 0.9)',
198
+ backgroundColor: 'rgba(255, 255, 255, 0.8)',
242
199
  alignItems: 'center',
243
200
  justifyContent: 'center',
244
201
  },
245
- loadingText: {
246
- fontSize: 16,
247
- color: '#666',
248
- marginTop: 16,
249
- textAlign: 'center',
250
- },
251
- debugContainer: {
252
- position: 'absolute',
253
- bottom: 0,
254
- left: 0,
255
- right: 0,
256
- backgroundColor: 'rgba(0, 0, 0, 0.8)',
257
- padding: 8,
258
- },
259
- debugText: {
260
- color: '#fff',
261
- fontSize: 12,
262
- fontFamily: 'monospace',
263
- },
264
202
  });
@@ -77,7 +77,7 @@ export const PIN_REQUIREMENTS = {
77
77
  };
78
78
 
79
79
  export const DEEP_LINK_CONFIG = {
80
- scheme: 'onairosevents',
81
- host: 'auth',
82
- redirectUri: 'onairosevents://auth/callback',
80
+ scheme: 'onairosanime',
81
+ host: 'authenticate',
82
+ redirectUri: 'onairosanime://auth/',
83
83
  };