@onairos/react-native 3.0.22 → 3.0.25

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 (39) hide show
  1. package/lib/commonjs/components/OnairosButton.js +2 -3
  2. package/lib/commonjs/components/OnairosButton.js.map +1 -1
  3. package/lib/commonjs/components/TrainingModal.js +120 -16
  4. package/lib/commonjs/components/TrainingModal.js.map +1 -1
  5. package/lib/commonjs/components/UniversalOnboarding.js +242 -39
  6. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  7. package/lib/commonjs/components/onboarding/OAuthWebView.js +138 -27
  8. package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
  9. package/lib/commonjs/constants/index.js +3 -2
  10. package/lib/commonjs/constants/index.js.map +1 -1
  11. package/lib/commonjs/services/platformAuthService.js +227 -0
  12. package/lib/commonjs/services/platformAuthService.js.map +1 -0
  13. package/lib/module/components/OnairosButton.js +2 -3
  14. package/lib/module/components/OnairosButton.js.map +1 -1
  15. package/lib/module/components/TrainingModal.js +120 -17
  16. package/lib/module/components/TrainingModal.js.map +1 -1
  17. package/lib/module/components/UniversalOnboarding.js +243 -40
  18. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  19. package/lib/module/components/onboarding/OAuthWebView.js +139 -28
  20. package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
  21. package/lib/module/constants/index.js +3 -2
  22. package/lib/module/constants/index.js.map +1 -1
  23. package/lib/module/services/platformAuthService.js +213 -0
  24. package/lib/module/services/platformAuthService.js.map +1 -0
  25. package/lib/typescript/components/OnairosButton.d.ts.map +1 -1
  26. package/lib/typescript/components/TrainingModal.d.ts.map +1 -1
  27. package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
  28. package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
  29. package/lib/typescript/constants/index.d.ts +1 -0
  30. package/lib/typescript/constants/index.d.ts.map +1 -1
  31. package/lib/typescript/services/platformAuthService.d.ts +45 -0
  32. package/lib/typescript/services/platformAuthService.d.ts.map +1 -0
  33. package/package.json +2 -1
  34. package/src/components/OnairosButton.tsx +1 -4
  35. package/src/components/TrainingModal.tsx +202 -61
  36. package/src/components/UniversalOnboarding.tsx +232 -35
  37. package/src/components/onboarding/OAuthWebView.tsx +135 -25
  38. package/src/constants/index.ts +3 -2
  39. package/src/services/platformAuthService.ts +241 -0
@@ -48,5 +48,6 @@ export declare const PIN_REQUIREMENTS: {
48
48
  export declare const DEEP_LINK_CONFIG: {
49
49
  scheme: string;
50
50
  host: string;
51
+ redirectUri: string;
51
52
  };
52
53
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;CAkBlB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAyBpD,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;CAczB,CAAC;AAEF,eAAO,MAAM,YAAY;;;CAGxB,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;CAM5B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;CAG5B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;CAkBlB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAyBpD,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;CAczB,CAAC;AAEF,eAAO,MAAM,YAAY;;;CAGxB,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;CAM5B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;CAI5B,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Checks if a native SDK is available for the given platform
3
+ */
4
+ export declare const hasNativeSDK: (platform: string) => boolean;
5
+ /**
6
+ * Gets the auth endpoint URL for a platform
7
+ */
8
+ export declare const getAuthEndpoint: (platform: string) => string;
9
+ /**
10
+ * Gets the color associated with a platform
11
+ */
12
+ export declare const getPlatformColor: (platform: string) => string;
13
+ /**
14
+ * Initiates the OAuth flow for a platform using Onairos proxy
15
+ * @param platform The platform to authenticate with
16
+ * @param userEmail The authenticated user's email (not random username)
17
+ * @returns A Promise that resolves to the OAuth URL to open in a WebView
18
+ */
19
+ export declare const initiateOAuth: (platform: string, userEmail: string) => Promise<string | null>;
20
+ /**
21
+ * Initiates the native SDK authentication flow for a platform
22
+ * @param platform The platform to authenticate with
23
+ * @returns A Promise that resolves to the authentication result
24
+ */
25
+ export declare const initiateNativeAuth: (platform: string) => Promise<boolean>;
26
+ /**
27
+ * Handles the OAuth callback
28
+ * @param url The callback URL
29
+ * @returns The authorization code extracted from the URL
30
+ */
31
+ export declare const handleOAuthCallback: (url: string) => string | null;
32
+ /**
33
+ * Checks if a URL is an OAuth callback
34
+ * @param url The URL to check
35
+ * @returns True if the URL is an OAuth callback
36
+ */
37
+ export declare const isOAuthCallback: (url: string) => boolean;
38
+ /**
39
+ * Detects if OAuth flow has completed successfully based on URL patterns
40
+ * @param url The current URL in the WebView
41
+ * @param platform The platform being authenticated
42
+ * @returns True if the OAuth flow has completed successfully
43
+ */
44
+ export declare const isOAuthSuccess: (url: string, platform: string) => boolean;
45
+ //# sourceMappingURL=platformAuthService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformAuthService.d.ts","sourceRoot":"","sources":["../../../src/services/platformAuthService.ts"],"names":[],"mappings":"AAwCA;;GAEG;AACH,eAAO,MAAM,YAAY,aAAc,MAAM,KAAG,OAG/C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,aAAc,MAAM,KAAG,MAGlD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,aAAc,MAAM,KAAG,MAGnD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,aAAoB,MAAM,aAAa,MAAM,KAAG,QAAQ,MAAM,GAAG,IAAI,CAmE9F,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAAoB,MAAM,KAAG,QAAQ,OAAO,CAS1E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QAAS,MAAM,KAAG,MAAM,GAAG,IAgB1D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAS,MAAM,KAAG,OAS7C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAAS,MAAM,YAAY,MAAM,KAAG,OAwC9D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onairos/react-native",
3
- "version": "3.0.22",
3
+ "version": "3.0.25",
4
4
  "description": "Onairos React Native SDK for social media authentication and AI model training",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -64,6 +64,7 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "@react-native-community/netinfo": "^9.0.0",
67
+ "@react-native-google-signin/google-signin": "^14.0.1",
67
68
  "axios": "^1.6.2",
68
69
  "react-native-crypto-js": "^1.0.0",
69
70
  "react-native-device-info": "^10.8.0",
@@ -15,7 +15,6 @@ import { COLORS } from '../constants';
15
15
  import type { OnairosButtonProps } from '../types';
16
16
  import { hasCredentials, getCredentials, deleteCredentials as clearCredentials } from '../utils/secureStorage';
17
17
  import { onairosApi } from '../api';
18
- import { Portal } from '../utils/Portal';
19
18
 
20
19
  export interface OnairosButtonRef {
21
20
  trigger: () => Promise<void>;
@@ -304,9 +303,8 @@ export const OnairosButton = forwardRef<OnairosButtonRef, OnairosButtonProps>(({
304
303
  />
305
304
  )}
306
305
 
307
- {/* Overlay rendered through Portal to ensure it appears at root level */}
306
+ {/* Overlay rendered directly without Portal */}
308
307
  {showOverlay && storedCredentials && (
309
- <Portal>
310
308
  <Overlay
311
309
  data={requestData || {}}
312
310
  username={storedCredentials.username}
@@ -315,7 +313,6 @@ export const OnairosButton = forwardRef<OnairosButtonRef, OnairosButtonProps>(({
315
313
  appName={AppName}
316
314
  darkMode={darkMode}
317
315
  />
318
- </Portal>
319
316
  )}
320
317
  </>
321
318
  );
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import {
3
3
  View,
4
4
  Text,
@@ -10,6 +10,9 @@ import {
10
10
  Animated,
11
11
  TouchableWithoutFeedback,
12
12
  SafeAreaView,
13
+ TextInput,
14
+ KeyboardAvoidingView,
15
+ Platform,
13
16
  } from 'react-native';
14
17
  import Icon from 'react-native-vector-icons/MaterialIcons';
15
18
  import { COLORS } from '../constants';
@@ -17,6 +20,18 @@ import type { TrainingModalProps } from '../types';
17
20
 
18
21
  const { width, height } = Dimensions.get('window');
19
22
 
23
+ // Dynamic training messages that appear during the process
24
+ const TRAINING_MESSAGES = [
25
+ "Loading your data...",
26
+ "Analyzing your digital footprint...",
27
+ "Your mind is very unique...",
28
+ "Creating your AI persona...",
29
+ "Building neural pathways...",
30
+ "Finalizing your digital twin...",
31
+ "Almost ready...",
32
+ "Training complete!"
33
+ ];
34
+
20
35
  export const TrainingModal: React.FC<TrainingModalProps> = ({
21
36
  visible,
22
37
  progress,
@@ -26,8 +41,47 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
26
41
  modelKey,
27
42
  username,
28
43
  }) => {
44
+ const [email, setEmail] = useState<string>('');
45
+ const [showEmailInput, setShowEmailInput] = useState<boolean>(false);
46
+ const [currentMessage, setCurrentMessage] = useState<string>(TRAINING_MESSAGES[0]);
47
+ const [messageIndex, setMessageIndex] = useState<number>(0);
48
+
29
49
  const progressPercentage = Math.round(progress * 100);
30
50
 
51
+ // Update training message based on progress
52
+ useEffect(() => {
53
+ if (progress > 0) {
54
+ const newIndex = Math.min(
55
+ Math.floor(progress * TRAINING_MESSAGES.length),
56
+ TRAINING_MESSAGES.length - 1
57
+ );
58
+
59
+ if (newIndex !== messageIndex) {
60
+ setMessageIndex(newIndex);
61
+ setCurrentMessage(TRAINING_MESSAGES[newIndex]);
62
+ }
63
+ }
64
+ }, [progress, messageIndex]);
65
+
66
+ // Show email input when training is complete
67
+ useEffect(() => {
68
+ if (progress >= 1 && !showEmailInput) {
69
+ setShowEmailInput(true);
70
+ }
71
+ }, [progress, showEmailInput]);
72
+
73
+ const handleEmailSubmit = () => {
74
+ if (email.trim() && onComplete) {
75
+ // Pass email data to the completion handler
76
+ onComplete();
77
+ }
78
+ };
79
+
80
+ const isValidEmail = (email: string): boolean => {
81
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
82
+ return emailRegex.test(email);
83
+ };
84
+
31
85
  return (
32
86
  <Modal
33
87
  visible={visible}
@@ -36,65 +90,119 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
36
90
  statusBarTranslucent
37
91
  onRequestClose={onCancel}
38
92
  >
39
- <TouchableWithoutFeedback>
40
- <View style={styles.modalOverlay}>
41
- <TouchableWithoutFeedback>
42
- <View style={styles.bottomSheet}>
43
- <View style={styles.handleContainer}>
44
- <View style={styles.handle} />
45
- </View>
46
-
47
- <SafeAreaView style={styles.container}>
48
- <View style={styles.content}>
49
- <Icon name="auto_awesome" size={48} color={COLORS.primary} />
50
-
51
- <Text style={styles.title}>Training Your AI Model</Text>
52
- <Text style={styles.subtitle}>
53
- We're analyzing your social media data to create your personalized AI model
54
- </Text>
55
-
56
- <View style={styles.progressContainer}>
57
- <View style={styles.progressBar}>
58
- <View
59
- style={[
60
- styles.progressFill,
61
- { width: `${progressPercentage}%` },
62
- ]}
63
- />
64
- </View>
65
- <Text style={styles.progressText}>{progressPercentage}%</Text>
66
- </View>
93
+ <KeyboardAvoidingView
94
+ style={styles.modalOverlay}
95
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
96
+ >
97
+ <TouchableWithoutFeedback>
98
+ <View style={styles.modalOverlay}>
99
+ <TouchableWithoutFeedback>
100
+ <View style={styles.bottomSheet}>
101
+ <View style={styles.handleContainer}>
102
+ <View style={styles.handle} />
103
+ </View>
104
+
105
+ <SafeAreaView style={styles.container}>
106
+ <View style={styles.content}>
107
+ {!showEmailInput ? (
108
+ <>
109
+ {/* Training in progress */}
110
+ <Icon name="auto_awesome" size={48} color={COLORS.primary} />
111
+
112
+ <Text style={styles.title}>Training Your AI Model</Text>
113
+ <Text style={styles.subtitle}>
114
+ We're analyzing your social media data to create your personalized AI model
115
+ </Text>
67
116
 
68
- <Text style={styles.etaText}>Estimated time remaining: {eta}</Text>
117
+ <View style={styles.progressContainer}>
118
+ <View style={styles.progressBar}>
119
+ <Animated.View
120
+ style={[
121
+ styles.progressFill,
122
+ { width: `${progressPercentage}%` },
123
+ ]}
124
+ />
125
+ </View>
126
+ <Text style={styles.progressText}>{progressPercentage}%</Text>
127
+ </View>
69
128
 
70
- <View style={styles.loadingContainer}>
71
- <ActivityIndicator size="small" color={COLORS.primary} />
72
- <Text style={styles.loadingText}>Processing your data...</Text>
73
- </View>
129
+ <Text style={styles.etaText}>Estimated time remaining: {eta}</Text>
74
130
 
75
- <View style={styles.footer}>
76
- <TouchableOpacity
77
- style={styles.cancelButton}
78
- onPress={onCancel}
79
- >
80
- <Text style={styles.cancelButtonText}>Cancel</Text>
81
- </TouchableOpacity>
82
-
83
- {progress >= 1 && (
84
- <TouchableOpacity
85
- style={styles.completeButton}
86
- onPress={onComplete}
87
- >
88
- <Text style={styles.completeButtonText}>Complete</Text>
89
- </TouchableOpacity>
131
+ <View style={styles.loadingContainer}>
132
+ <ActivityIndicator size="small" color={COLORS.primary} />
133
+ <Text style={styles.loadingText}>{currentMessage}</Text>
134
+ </View>
135
+
136
+ <View style={styles.footer}>
137
+ <TouchableOpacity
138
+ style={styles.cancelButton}
139
+ onPress={onCancel}
140
+ >
141
+ <Text style={styles.cancelButtonText}>Cancel</Text>
142
+ </TouchableOpacity>
143
+ </View>
144
+ </>
145
+ ) : (
146
+ <>
147
+ {/* Training complete - Email input */}
148
+ <Icon name="check_circle" size={48} color="#4CAF50" />
149
+
150
+ <Text style={styles.title}>Training Complete!</Text>
151
+ <Text style={styles.subtitle}>
152
+ Your AI model is ready. Enter your email to receive your account details and access your digital twin.
153
+ </Text>
154
+
155
+ <View style={styles.emailContainer}>
156
+ <Text style={styles.emailLabel}>Email Address</Text>
157
+ <TextInput
158
+ style={styles.emailInput}
159
+ placeholder="Enter your email address"
160
+ placeholderTextColor="#999"
161
+ value={email}
162
+ onChangeText={setEmail}
163
+ keyboardType="email-address"
164
+ autoCapitalize="none"
165
+ autoCorrect={false}
166
+ autoComplete="email"
167
+ />
168
+ <Text style={styles.emailHint}>
169
+ We'll send you login credentials and access to your AI persona
170
+ </Text>
171
+ </View>
172
+
173
+ <View style={styles.footer}>
174
+ <TouchableOpacity
175
+ style={styles.cancelButton}
176
+ onPress={onCancel}
177
+ >
178
+ <Text style={styles.cancelButtonText}>Cancel</Text>
179
+ </TouchableOpacity>
180
+
181
+ <TouchableOpacity
182
+ style={[
183
+ styles.completeButton,
184
+ !isValidEmail(email) && styles.completeButtonDisabled
185
+ ]}
186
+ onPress={handleEmailSubmit}
187
+ disabled={!isValidEmail(email)}
188
+ >
189
+ <Text style={[
190
+ styles.completeButtonText,
191
+ !isValidEmail(email) && styles.completeButtonTextDisabled
192
+ ]}>
193
+ Complete Setup
194
+ </Text>
195
+ </TouchableOpacity>
196
+ </View>
197
+ </>
90
198
  )}
91
199
  </View>
92
- </View>
93
- </SafeAreaView>
94
- </View>
95
- </TouchableWithoutFeedback>
96
- </View>
97
- </TouchableWithoutFeedback>
200
+ </SafeAreaView>
201
+ </View>
202
+ </TouchableWithoutFeedback>
203
+ </View>
204
+ </TouchableWithoutFeedback>
205
+ </KeyboardAvoidingView>
98
206
  </Modal>
99
207
  );
100
208
  };
@@ -109,7 +217,7 @@ const styles = StyleSheet.create({
109
217
  bottomSheet: {
110
218
  backgroundColor: '#fff',
111
219
  width: width,
112
- height: height * 0.6,
220
+ height: height * 0.7,
113
221
  borderTopLeftRadius: 24,
114
222
  borderTopRightRadius: 24,
115
223
  overflow: 'hidden',
@@ -150,6 +258,7 @@ const styles = StyleSheet.create({
150
258
  color: COLORS.text.secondary,
151
259
  textAlign: 'center',
152
260
  marginBottom: 32,
261
+ lineHeight: 22,
153
262
  },
154
263
  progressContainer: {
155
264
  width: '100%',
@@ -183,9 +292,37 @@ const styles = StyleSheet.create({
183
292
  marginBottom: 32,
184
293
  },
185
294
  loadingText: {
295
+ fontSize: 16,
296
+ color: COLORS.text.primary,
297
+ marginLeft: 12,
298
+ fontWeight: '500',
299
+ },
300
+ emailContainer: {
301
+ width: '100%',
302
+ marginBottom: 32,
303
+ },
304
+ emailLabel: {
305
+ fontSize: 16,
306
+ fontWeight: '600',
307
+ color: COLORS.text.primary,
308
+ marginBottom: 8,
309
+ },
310
+ emailInput: {
311
+ width: '100%',
312
+ height: 48,
313
+ borderWidth: 1,
314
+ borderColor: '#E0E0E0',
315
+ borderRadius: 12,
316
+ paddingHorizontal: 16,
317
+ fontSize: 16,
318
+ color: COLORS.text.primary,
319
+ backgroundColor: '#F8F8F8',
320
+ },
321
+ emailHint: {
186
322
  fontSize: 14,
187
323
  color: COLORS.text.secondary,
188
- marginLeft: 8,
324
+ marginTop: 8,
325
+ textAlign: 'center',
189
326
  },
190
327
  footer: {
191
328
  flexDirection: 'row',
@@ -210,13 +347,17 @@ const styles = StyleSheet.create({
210
347
  paddingVertical: 16,
211
348
  paddingHorizontal: 32,
212
349
  borderRadius: 16,
213
- backgroundColor: '#fff',
214
- borderWidth: 1,
215
- borderColor: '#000',
350
+ backgroundColor: '#000',
351
+ },
352
+ completeButtonDisabled: {
353
+ backgroundColor: '#E0E0E0',
216
354
  },
217
355
  completeButtonText: {
218
356
  fontSize: 16,
219
357
  fontWeight: '600',
220
- color: '#000',
358
+ color: '#fff',
359
+ },
360
+ completeButtonTextDisabled: {
361
+ color: '#999',
221
362
  },
222
363
  });