@onairos/react-native 3.0.50 → 3.0.52
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/EmailVerificationModal.js +317 -0
- package/lib/commonjs/components/EmailVerificationModal.js.map +1 -0
- package/lib/commonjs/components/TrainingModal.js +66 -75
- package/lib/commonjs/components/TrainingModal.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +32 -5
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/index.js +31 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/services/platformAuthService.js +156 -1
- package/lib/commonjs/services/platformAuthService.js.map +1 -1
- package/lib/module/components/EmailVerificationModal.js +308 -0
- package/lib/module/components/EmailVerificationModal.js.map +1 -0
- package/lib/module/components/TrainingModal.js +66 -75
- package/lib/module/components/TrainingModal.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +29 -2
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/index.js +8 -69
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/platformAuthService.js +151 -0
- package/lib/module/services/platformAuthService.js.map +1 -1
- package/lib/typescript/components/EmailVerificationModal.d.ts +10 -0
- package/lib/typescript/components/EmailVerificationModal.d.ts.map +1 -0
- package/lib/typescript/components/TrainingModal.d.ts.map +1 -1
- package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +4 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/services/platformAuthService.d.ts +29 -0
- package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/EmailVerificationModal.tsx +356 -0
- package/src/components/TrainingModal.tsx +69 -73
- package/src/components/UniversalOnboarding.tsx +34 -7
- package/src/index.ts +7 -1
- package/src/services/platformAuthService.ts +176 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onairos/react-native",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.52",
|
|
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",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"registry": "https://registry.npmjs.org/"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
+
"@opacity-labs/react-native-opacity": "^5.6.2",
|
|
66
67
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
67
68
|
"@react-native-community/netinfo": "^9.0.0",
|
|
68
69
|
"@react-native-google-signin/google-signin": "^14.0.1",
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import React, { useState, useCallback } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
ActivityIndicator,
|
|
8
|
+
Modal,
|
|
9
|
+
SafeAreaView,
|
|
10
|
+
TouchableWithoutFeedback,
|
|
11
|
+
TextInput,
|
|
12
|
+
Alert,
|
|
13
|
+
} from 'react-native';
|
|
14
|
+
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
15
|
+
import { requestEmailVerification, verifyEmailCode, checkEmailVerificationStatus } from '../services/platformAuthService';
|
|
16
|
+
|
|
17
|
+
export interface EmailVerificationModalProps {
|
|
18
|
+
visible: boolean;
|
|
19
|
+
email: string;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
onVerificationComplete: (email: string, isExistingUser: boolean) => void;
|
|
22
|
+
onVerificationFailed: (error: string) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const EmailVerificationModal: React.FC<EmailVerificationModalProps> = ({
|
|
26
|
+
visible,
|
|
27
|
+
email,
|
|
28
|
+
onClose,
|
|
29
|
+
onVerificationComplete,
|
|
30
|
+
onVerificationFailed,
|
|
31
|
+
}) => {
|
|
32
|
+
const [step, setStep] = useState<'request' | 'verify'>('request');
|
|
33
|
+
const [verificationCode, setVerificationCode] = useState<string>('');
|
|
34
|
+
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
35
|
+
const [codeSent, setCodeSent] = useState<boolean>(false);
|
|
36
|
+
|
|
37
|
+
const handleRequestVerification = useCallback(async () => {
|
|
38
|
+
if (!email) {
|
|
39
|
+
Alert.alert('Error', 'Email address is required');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setIsLoading(true);
|
|
44
|
+
try {
|
|
45
|
+
console.log('📧 Requesting email verification for:', email);
|
|
46
|
+
|
|
47
|
+
// First check if there's already a pending verification
|
|
48
|
+
const statusCheck = await checkEmailVerificationStatus(email);
|
|
49
|
+
if (statusCheck.success && statusCheck.isPending) {
|
|
50
|
+
console.log('✅ Email verification already pending');
|
|
51
|
+
setCodeSent(true);
|
|
52
|
+
setStep('verify');
|
|
53
|
+
setIsLoading(false);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Request new verification code
|
|
58
|
+
const result = await requestEmailVerification(email);
|
|
59
|
+
|
|
60
|
+
if (result.success) {
|
|
61
|
+
console.log('✅ Email verification code requested successfully');
|
|
62
|
+
setCodeSent(true);
|
|
63
|
+
setStep('verify');
|
|
64
|
+
Alert.alert(
|
|
65
|
+
'Verification Code Sent',
|
|
66
|
+
result.message || 'Please check your email for the verification code.\n\nNote: In testing mode, any code will work.',
|
|
67
|
+
[{ text: 'OK', style: 'default' }]
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
console.error('❌ Failed to request verification code:', result.error);
|
|
71
|
+
Alert.alert('Error', result.error || 'Failed to send verification code');
|
|
72
|
+
onVerificationFailed(result.error || 'Failed to send verification code');
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('❌ Error requesting verification:', error);
|
|
76
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
77
|
+
Alert.alert('Error', errorMessage);
|
|
78
|
+
onVerificationFailed(errorMessage);
|
|
79
|
+
} finally {
|
|
80
|
+
setIsLoading(false);
|
|
81
|
+
}
|
|
82
|
+
}, [email, onVerificationFailed]);
|
|
83
|
+
|
|
84
|
+
const handleVerifyCode = useCallback(async () => {
|
|
85
|
+
if (!verificationCode.trim()) {
|
|
86
|
+
Alert.alert('Error', 'Please enter the verification code');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
setIsLoading(true);
|
|
91
|
+
try {
|
|
92
|
+
console.log('🔍 Verifying email code for:', email);
|
|
93
|
+
|
|
94
|
+
const result = await verifyEmailCode(email, verificationCode.trim());
|
|
95
|
+
|
|
96
|
+
if (result.success) {
|
|
97
|
+
console.log('✅ Email verification successful');
|
|
98
|
+
|
|
99
|
+
// In a real implementation, you would determine if this is an existing user
|
|
100
|
+
// based on the verification response or additional API calls
|
|
101
|
+
// For now, we'll assume new users need full onboarding
|
|
102
|
+
const isExistingUser = false; // This should be determined by your backend logic
|
|
103
|
+
|
|
104
|
+
Alert.alert(
|
|
105
|
+
'Email Verified',
|
|
106
|
+
result.message || 'Your email has been verified successfully!',
|
|
107
|
+
[{
|
|
108
|
+
text: 'Continue',
|
|
109
|
+
onPress: () => {
|
|
110
|
+
onVerificationComplete(email, isExistingUser);
|
|
111
|
+
}
|
|
112
|
+
}]
|
|
113
|
+
);
|
|
114
|
+
} else {
|
|
115
|
+
console.error('❌ Email verification failed:', result.error);
|
|
116
|
+
Alert.alert('Verification Failed', result.error || 'Invalid verification code. Please try again.');
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('❌ Error verifying code:', error);
|
|
120
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
121
|
+
Alert.alert('Error', errorMessage);
|
|
122
|
+
} finally {
|
|
123
|
+
setIsLoading(false);
|
|
124
|
+
}
|
|
125
|
+
}, [email, verificationCode, onVerificationComplete]);
|
|
126
|
+
|
|
127
|
+
const handleResendCode = useCallback(async () => {
|
|
128
|
+
setVerificationCode('');
|
|
129
|
+
await handleRequestVerification();
|
|
130
|
+
}, [handleRequestVerification]);
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<Modal
|
|
134
|
+
visible={visible}
|
|
135
|
+
transparent
|
|
136
|
+
animationType="slide"
|
|
137
|
+
statusBarTranslucent
|
|
138
|
+
onRequestClose={onClose}
|
|
139
|
+
>
|
|
140
|
+
<TouchableWithoutFeedback onPress={onClose}>
|
|
141
|
+
<View style={styles.modalOverlay}>
|
|
142
|
+
<TouchableWithoutFeedback onPress={e => e.stopPropagation()}>
|
|
143
|
+
<View style={styles.modalContent}>
|
|
144
|
+
<SafeAreaView style={styles.container}>
|
|
145
|
+
<View style={styles.header}>
|
|
146
|
+
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
|
147
|
+
<Icon name="close" size={24} color="#666" />
|
|
148
|
+
</TouchableOpacity>
|
|
149
|
+
<Text style={styles.headerTitle}>Email Verification</Text>
|
|
150
|
+
<View style={styles.placeholder} />
|
|
151
|
+
</View>
|
|
152
|
+
|
|
153
|
+
<View style={styles.content}>
|
|
154
|
+
{step === 'request' ? (
|
|
155
|
+
<>
|
|
156
|
+
<View style={styles.iconContainer}>
|
|
157
|
+
<Icon name="email" size={48} color="#4CAF50" />
|
|
158
|
+
</View>
|
|
159
|
+
|
|
160
|
+
<Text style={styles.title}>Verify Your Email</Text>
|
|
161
|
+
<Text style={styles.subtitle}>
|
|
162
|
+
We need to verify your email address to continue
|
|
163
|
+
</Text>
|
|
164
|
+
|
|
165
|
+
<View style={styles.emailContainer}>
|
|
166
|
+
<Text style={styles.emailLabel}>Email Address:</Text>
|
|
167
|
+
<Text style={styles.emailText}>{email}</Text>
|
|
168
|
+
</View>
|
|
169
|
+
|
|
170
|
+
<TouchableOpacity
|
|
171
|
+
style={[styles.button, isLoading && styles.buttonDisabled]}
|
|
172
|
+
onPress={handleRequestVerification}
|
|
173
|
+
disabled={isLoading}
|
|
174
|
+
>
|
|
175
|
+
{isLoading ? (
|
|
176
|
+
<ActivityIndicator size="small" color="#fff" />
|
|
177
|
+
) : (
|
|
178
|
+
<Text style={styles.buttonText}>Send Verification Code</Text>
|
|
179
|
+
)}
|
|
180
|
+
</TouchableOpacity>
|
|
181
|
+
</>
|
|
182
|
+
) : (
|
|
183
|
+
<>
|
|
184
|
+
<View style={styles.iconContainer}>
|
|
185
|
+
<Icon name="verified" size={48} color="#4CAF50" />
|
|
186
|
+
</View>
|
|
187
|
+
|
|
188
|
+
<Text style={styles.title}>Enter Verification Code</Text>
|
|
189
|
+
<Text style={styles.subtitle}>
|
|
190
|
+
We've sent a 6-digit code to {email}
|
|
191
|
+
</Text>
|
|
192
|
+
|
|
193
|
+
<Text style={styles.testingNote}>
|
|
194
|
+
🔍 Testing Mode: Any code will work for verification
|
|
195
|
+
</Text>
|
|
196
|
+
|
|
197
|
+
<TextInput
|
|
198
|
+
style={styles.codeInput}
|
|
199
|
+
value={verificationCode}
|
|
200
|
+
onChangeText={setVerificationCode}
|
|
201
|
+
placeholder="Enter 6-digit code"
|
|
202
|
+
keyboardType="number-pad"
|
|
203
|
+
maxLength={6}
|
|
204
|
+
autoFocus
|
|
205
|
+
textAlign="center"
|
|
206
|
+
/>
|
|
207
|
+
|
|
208
|
+
<TouchableOpacity
|
|
209
|
+
style={[styles.button, isLoading && styles.buttonDisabled]}
|
|
210
|
+
onPress={handleVerifyCode}
|
|
211
|
+
disabled={isLoading || !verificationCode.trim()}
|
|
212
|
+
>
|
|
213
|
+
{isLoading ? (
|
|
214
|
+
<ActivityIndicator size="small" color="#fff" />
|
|
215
|
+
) : (
|
|
216
|
+
<Text style={styles.buttonText}>Verify Code</Text>
|
|
217
|
+
)}
|
|
218
|
+
</TouchableOpacity>
|
|
219
|
+
|
|
220
|
+
<TouchableOpacity
|
|
221
|
+
style={styles.resendButton}
|
|
222
|
+
onPress={handleResendCode}
|
|
223
|
+
disabled={isLoading}
|
|
224
|
+
>
|
|
225
|
+
<Text style={styles.resendButtonText}>
|
|
226
|
+
Didn't receive the code? Resend
|
|
227
|
+
</Text>
|
|
228
|
+
</TouchableOpacity>
|
|
229
|
+
</>
|
|
230
|
+
)}
|
|
231
|
+
</View>
|
|
232
|
+
</SafeAreaView>
|
|
233
|
+
</View>
|
|
234
|
+
</TouchableWithoutFeedback>
|
|
235
|
+
</View>
|
|
236
|
+
</TouchableWithoutFeedback>
|
|
237
|
+
</Modal>
|
|
238
|
+
);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const styles = StyleSheet.create({
|
|
242
|
+
modalOverlay: {
|
|
243
|
+
flex: 1,
|
|
244
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
245
|
+
justifyContent: 'center',
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
},
|
|
248
|
+
modalContent: {
|
|
249
|
+
backgroundColor: '#fff',
|
|
250
|
+
borderRadius: 16,
|
|
251
|
+
width: '90%',
|
|
252
|
+
maxWidth: 400,
|
|
253
|
+
maxHeight: '80%',
|
|
254
|
+
},
|
|
255
|
+
container: {
|
|
256
|
+
padding: 24,
|
|
257
|
+
},
|
|
258
|
+
header: {
|
|
259
|
+
flexDirection: 'row',
|
|
260
|
+
alignItems: 'center',
|
|
261
|
+
justifyContent: 'space-between',
|
|
262
|
+
marginBottom: 24,
|
|
263
|
+
},
|
|
264
|
+
closeButton: {
|
|
265
|
+
padding: 8,
|
|
266
|
+
},
|
|
267
|
+
headerTitle: {
|
|
268
|
+
fontSize: 18,
|
|
269
|
+
fontWeight: '600',
|
|
270
|
+
color: '#000',
|
|
271
|
+
},
|
|
272
|
+
placeholder: {
|
|
273
|
+
width: 40,
|
|
274
|
+
},
|
|
275
|
+
content: {
|
|
276
|
+
alignItems: 'center',
|
|
277
|
+
},
|
|
278
|
+
iconContainer: {
|
|
279
|
+
marginBottom: 16,
|
|
280
|
+
},
|
|
281
|
+
title: {
|
|
282
|
+
fontSize: 24,
|
|
283
|
+
fontWeight: '600',
|
|
284
|
+
color: '#000',
|
|
285
|
+
textAlign: 'center',
|
|
286
|
+
marginBottom: 8,
|
|
287
|
+
},
|
|
288
|
+
subtitle: {
|
|
289
|
+
fontSize: 16,
|
|
290
|
+
color: '#666',
|
|
291
|
+
textAlign: 'center',
|
|
292
|
+
marginBottom: 24,
|
|
293
|
+
},
|
|
294
|
+
emailContainer: {
|
|
295
|
+
backgroundColor: '#f5f5f5',
|
|
296
|
+
padding: 16,
|
|
297
|
+
borderRadius: 8,
|
|
298
|
+
marginBottom: 24,
|
|
299
|
+
width: '100%',
|
|
300
|
+
},
|
|
301
|
+
emailLabel: {
|
|
302
|
+
fontSize: 14,
|
|
303
|
+
color: '#666',
|
|
304
|
+
marginBottom: 4,
|
|
305
|
+
},
|
|
306
|
+
emailText: {
|
|
307
|
+
fontSize: 16,
|
|
308
|
+
fontWeight: '500',
|
|
309
|
+
color: '#000',
|
|
310
|
+
},
|
|
311
|
+
testingNote: {
|
|
312
|
+
fontSize: 14,
|
|
313
|
+
color: '#FF9800',
|
|
314
|
+
textAlign: 'center',
|
|
315
|
+
marginBottom: 16,
|
|
316
|
+
backgroundColor: '#FFF3E0',
|
|
317
|
+
padding: 8,
|
|
318
|
+
borderRadius: 4,
|
|
319
|
+
},
|
|
320
|
+
codeInput: {
|
|
321
|
+
borderWidth: 1,
|
|
322
|
+
borderColor: '#ddd',
|
|
323
|
+
borderRadius: 8,
|
|
324
|
+
padding: 16,
|
|
325
|
+
fontSize: 18,
|
|
326
|
+
fontWeight: '600',
|
|
327
|
+
letterSpacing: 4,
|
|
328
|
+
marginBottom: 24,
|
|
329
|
+
width: '100%',
|
|
330
|
+
},
|
|
331
|
+
button: {
|
|
332
|
+
backgroundColor: '#4CAF50',
|
|
333
|
+
paddingVertical: 16,
|
|
334
|
+
paddingHorizontal: 32,
|
|
335
|
+
borderRadius: 8,
|
|
336
|
+
width: '100%',
|
|
337
|
+
alignItems: 'center',
|
|
338
|
+
marginBottom: 16,
|
|
339
|
+
},
|
|
340
|
+
buttonDisabled: {
|
|
341
|
+
opacity: 0.5,
|
|
342
|
+
},
|
|
343
|
+
buttonText: {
|
|
344
|
+
color: '#fff',
|
|
345
|
+
fontSize: 16,
|
|
346
|
+
fontWeight: '600',
|
|
347
|
+
},
|
|
348
|
+
resendButton: {
|
|
349
|
+
paddingVertical: 8,
|
|
350
|
+
},
|
|
351
|
+
resendButtonText: {
|
|
352
|
+
color: '#4CAF50',
|
|
353
|
+
fontSize: 14,
|
|
354
|
+
textDecorationLine: 'underline',
|
|
355
|
+
},
|
|
356
|
+
});
|
|
@@ -74,14 +74,12 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
74
74
|
|
|
75
75
|
console.log('📤 Sending training data:', trainingData);
|
|
76
76
|
|
|
77
|
-
//
|
|
78
|
-
// TODO: Uncomment when real authentication is available
|
|
79
|
-
/*
|
|
77
|
+
// Call the actual training API - backend confirmed this is working
|
|
80
78
|
const response = await fetch('https://api2.onairos.uk/enoch/trainModel/mobile', {
|
|
81
79
|
method: 'POST',
|
|
82
80
|
headers: {
|
|
83
81
|
'Content-Type': 'application/json',
|
|
84
|
-
'Authorization': `Bearer ${userToken}`
|
|
82
|
+
'Authorization': `Bearer ${userToken || 'temp-token'}` // Backend has JWT auth working
|
|
85
83
|
},
|
|
86
84
|
body: JSON.stringify(trainingData)
|
|
87
85
|
});
|
|
@@ -96,13 +94,11 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
96
94
|
console.error('Training start failed:', result.error);
|
|
97
95
|
setTrainingStatus(`Error: ${result.error}`);
|
|
98
96
|
setHasError(true);
|
|
97
|
+
// Fallback to simulation if API call fails
|
|
98
|
+
console.log('🚀 Falling back to simulated training');
|
|
99
|
+
setTrainingStatus('Training model...');
|
|
100
|
+
setInternalProgress(20);
|
|
99
101
|
}
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
// Simulate successful training start
|
|
103
|
-
console.log('🚀 Training Started (simulated)');
|
|
104
|
-
setTrainingStatus('Training model...');
|
|
105
|
-
setInternalProgress(20);
|
|
106
102
|
|
|
107
103
|
} catch (error) {
|
|
108
104
|
console.error('Training start error:', error);
|
|
@@ -118,70 +114,70 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
118
114
|
console.log('Setting up socket connection for training...');
|
|
119
115
|
console.log('🧑💻 User info available:', userInfo);
|
|
120
116
|
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
117
|
+
// Initialize real socket connection - backend confirmed this is working
|
|
118
|
+
try {
|
|
119
|
+
// Initialize socket connection
|
|
120
|
+
socketRef.current = io('https://api2.onairos.uk', {
|
|
121
|
+
transports: ['websocket'],
|
|
122
|
+
autoConnect: false
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Socket event listeners
|
|
126
|
+
socketRef.current.on('connect', () => {
|
|
127
|
+
console.log('✅ Socket connected for training');
|
|
128
|
+
setSocketConnected(true);
|
|
129
|
+
const socketId = socketRef.current?.id;
|
|
130
|
+
if (socketId) {
|
|
131
|
+
startEnochTraining(socketId);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
socketRef.current.on('disconnect', () => {
|
|
136
|
+
console.log('❌ Socket disconnected');
|
|
137
|
+
setSocketConnected(false);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
socketRef.current.on('trainingCompleted', (data) => {
|
|
141
|
+
console.log('✅ Training Complete:', data);
|
|
142
|
+
setTrainingStatus('Running test inference...');
|
|
143
|
+
setInternalProgress(60);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
socketRef.current.on('inferenceCompleted', (data) => {
|
|
147
|
+
console.log('🧠 Inference Complete:', data);
|
|
148
|
+
setTrainingStatus('Uploading to S3...');
|
|
149
|
+
setInternalProgress(80);
|
|
150
|
+
setUserTraits(data.traits);
|
|
151
|
+
setInferenceResults(data.inferenceResults);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
socketRef.current.on('modelStandby', (data) => {
|
|
155
|
+
console.log('🎉 All Complete:', data);
|
|
156
|
+
setIsTrainingComplete(true);
|
|
157
|
+
setTrainingStatus('Complete!');
|
|
158
|
+
setInternalProgress(100);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
socketRef.current.on('trainingUpdate', (data) => {
|
|
162
|
+
if (data.error) {
|
|
163
|
+
console.error('Training update error:', data.error);
|
|
164
|
+
setTrainingStatus(`Error: ${data.error}`);
|
|
165
|
+
setHasError(true);
|
|
166
|
+
} else if (data.progress) {
|
|
167
|
+
setInternalProgress(data.progress);
|
|
168
|
+
setTrainingStatus(data.status || 'Training in progress...');
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Connect to socket
|
|
173
|
+
socketRef.current.connect();
|
|
174
|
+
} catch (socketError) {
|
|
175
|
+
console.error('Socket connection failed, falling back to simulation:', socketError);
|
|
176
|
+
// Fallback to simulation if socket fails
|
|
177
|
+
console.log('🔌 Falling back to simulated socket connection...');
|
|
133
178
|
setSocketConnected(true);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
startEnochTraining(socketId);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
socketRef.current.on('disconnect', () => {
|
|
141
|
-
console.log('❌ Socket disconnected');
|
|
142
|
-
setSocketConnected(false);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
socketRef.current.on('trainingCompleted', (data) => {
|
|
146
|
-
console.log('✅ Training Complete:', data);
|
|
147
|
-
setTrainingStatus('Running test inference...');
|
|
148
|
-
setInternalProgress(60);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
socketRef.current.on('inferenceCompleted', (data) => {
|
|
152
|
-
console.log('🧠 Inference Complete:', data);
|
|
153
|
-
setTrainingStatus('Uploading to S3...');
|
|
154
|
-
setInternalProgress(80);
|
|
155
|
-
setUserTraits(data.traits);
|
|
156
|
-
setInferenceResults(data.inferenceResults);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
socketRef.current.on('modelStandby', (data) => {
|
|
160
|
-
console.log('🎉 All Complete:', data);
|
|
161
|
-
setIsTrainingComplete(true);
|
|
162
|
-
setTrainingStatus('Complete!');
|
|
163
|
-
setInternalProgress(100);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
socketRef.current.on('trainingUpdate', (data) => {
|
|
167
|
-
if (data.error) {
|
|
168
|
-
console.error('Training update error:', data.error);
|
|
169
|
-
setTrainingStatus(`Error: ${data.error}`);
|
|
170
|
-
setHasError(true);
|
|
171
|
-
} else if (data.progress) {
|
|
172
|
-
setInternalProgress(data.progress);
|
|
173
|
-
setTrainingStatus(data.status || 'Training in progress...');
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
// Connect to socket
|
|
178
|
-
socketRef.current.connect();
|
|
179
|
-
*/
|
|
180
|
-
|
|
181
|
-
// Simulate socket connection and training for now
|
|
182
|
-
console.log('🔌 Simulating socket connection...');
|
|
183
|
-
setSocketConnected(true);
|
|
184
|
-
startEnochTraining('simulated-socket-id');
|
|
179
|
+
startEnochTraining('simulated-socket-id');
|
|
180
|
+
}
|
|
185
181
|
|
|
186
182
|
// Cleanup function
|
|
187
183
|
return () => {
|
|
@@ -24,13 +24,23 @@ import { TrainingModal } from './TrainingModal';
|
|
|
24
24
|
import { OAuthWebView } from './onboarding/OAuthWebView';
|
|
25
25
|
import { useConnections } from '../hooks/useConnections';
|
|
26
26
|
import { COLORS, DEEP_LINK_CONFIG } from '../constants';
|
|
27
|
-
import { initiateOAuth, initiateNativeAuth, hasNativeSDK, isOAuthCallback, testApiConnectivity, handleOAuthCallbackUrl, refreshYouTubeTokens } from '../services/platformAuthService';
|
|
27
|
+
import { initiateOAuth, initiateNativeAuth, hasNativeSDK, isOAuthCallback, testApiConnectivity, handleOAuthCallbackUrl, refreshYouTubeTokens, requestEmailVerification, verifyEmailCode, checkEmailVerificationStatus, disconnectPlatform } from '../services/platformAuthService';
|
|
28
28
|
import type { UniversalOnboardingProps, ConnectionStatus } from '../types';
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
|
|
30
|
+
// Optional Opacity SDK imports with error handling
|
|
31
|
+
let opacityInit: any = null;
|
|
32
|
+
let OpacityEnvironment: any = null;
|
|
33
|
+
let opacityGet: any = null;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const opacitySDK = require('@opacity-labs/react-native-opacity');
|
|
37
|
+
opacityInit = opacitySDK.init;
|
|
38
|
+
OpacityEnvironment = opacitySDK.OpacityEnvironment;
|
|
39
|
+
opacityGet = opacitySDK.get;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.warn('Opacity SDK not available:', error);
|
|
42
|
+
// Opacity SDK will be disabled if not available
|
|
43
|
+
}
|
|
34
44
|
|
|
35
45
|
const { height, width } = Dimensions.get('window');
|
|
36
46
|
|
|
@@ -223,8 +233,25 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
223
233
|
|
|
224
234
|
console.log('✅ API connectivity confirmed');
|
|
225
235
|
|
|
226
|
-
// Instagram: Use Opacity SDK exclusively
|
|
236
|
+
// Instagram: Use Opacity SDK exclusively (if available)
|
|
227
237
|
if (platformId === 'instagram') {
|
|
238
|
+
// Check if Opacity SDK is available
|
|
239
|
+
if (!opacityInit || !OpacityEnvironment || !opacityGet) {
|
|
240
|
+
console.warn('⚠️ Opacity SDK not available, falling back to OAuth for Instagram');
|
|
241
|
+
// Fall back to OAuth flow for Instagram
|
|
242
|
+
const oauthUrl = await initiateOAuth(platformId, username, AppName);
|
|
243
|
+
|
|
244
|
+
if (oauthUrl) {
|
|
245
|
+
console.log(`✅ Received OAuth URL for ${platformId}:`, oauthUrl);
|
|
246
|
+
setCurrentPlatform(platformId);
|
|
247
|
+
setOauthUrl(oauthUrl);
|
|
248
|
+
setStep('oauth');
|
|
249
|
+
} else {
|
|
250
|
+
throw new Error(`Failed to get authorization URL for ${platformId}. Please try again.`);
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
228
255
|
console.log('🔌 Initializing Opacity SDK for Instagram...');
|
|
229
256
|
|
|
230
257
|
// Initialize Opacity SDK with your API key
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,8 @@ export type {
|
|
|
21
21
|
PinRequirements,
|
|
22
22
|
} from './types';
|
|
23
23
|
|
|
24
|
+
export type { EmailVerificationModalProps } from './components/EmailVerificationModal';
|
|
25
|
+
|
|
24
26
|
export type { StorageOptions, OnairosCredentials } from './utils/secureStorage';
|
|
25
27
|
export type { OAuthConfig } from './services/oauthService';
|
|
26
28
|
export type { ApiErrorType, ApiError } from './utils/onairosApi';
|
|
@@ -64,7 +66,6 @@ export {
|
|
|
64
66
|
// Export services
|
|
65
67
|
export {
|
|
66
68
|
connectPlatform,
|
|
67
|
-
disconnectPlatform,
|
|
68
69
|
initializeOAuthService,
|
|
69
70
|
cleanupOAuthService,
|
|
70
71
|
storePlatformConnection,
|
|
@@ -75,6 +76,10 @@ export {
|
|
|
75
76
|
refreshYouTubeTokens,
|
|
76
77
|
hasNativeSDK,
|
|
77
78
|
testApiConnectivity,
|
|
79
|
+
requestEmailVerification,
|
|
80
|
+
verifyEmailCode,
|
|
81
|
+
checkEmailVerificationStatus,
|
|
82
|
+
disconnectPlatform,
|
|
78
83
|
} from './services/platformAuthService';
|
|
79
84
|
|
|
80
85
|
// Export API and Services
|
|
@@ -104,6 +109,7 @@ export { OnboardingHeader } from './components/onboarding/OnboardingHeader';
|
|
|
104
109
|
export { PlatformList } from './components/PlatformList';
|
|
105
110
|
export { PinInput } from './components/PinInput';
|
|
106
111
|
export { TrainingModal } from './components/TrainingModal';
|
|
112
|
+
export { EmailVerificationModal } from './components/EmailVerificationModal';
|
|
107
113
|
export { Overlay } from './components/Overlay';
|
|
108
114
|
export { UniversalOnboarding } from './components/UniversalOnboarding';
|
|
109
115
|
export { OnairosButton } from './components/OnairosButton';
|