@onairos/react-native 3.0.24 → 3.0.26
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/OnairosButton.js +2 -3
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/TrainingModal.js +120 -16
- package/lib/commonjs/components/TrainingModal.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +196 -94
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/components/onboarding/OAuthWebView.js +138 -27
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/constants/index.js +3 -3
- package/lib/commonjs/constants/index.js.map +1 -1
- package/lib/commonjs/services/platformAuthService.js +95 -44
- package/lib/commonjs/services/platformAuthService.js.map +1 -1
- package/lib/module/components/OnairosButton.js +2 -3
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/TrainingModal.js +120 -17
- package/lib/module/components/TrainingModal.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +197 -95
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +139 -28
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/constants/index.js +3 -3
- package/lib/module/constants/index.js.map +1 -1
- package/lib/module/services/platformAuthService.js +92 -42
- package/lib/module/services/platformAuthService.js.map +1 -1
- package/lib/typescript/components/OnairosButton.d.ts.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/services/platformAuthService.d.ts +11 -4
- package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/OnairosButton.tsx +1 -4
- package/src/components/TrainingModal.tsx +202 -61
- package/src/components/UniversalOnboarding.tsx +188 -83
- package/src/components/onboarding/OAuthWebView.tsx +135 -25
- package/src/constants/index.ts +3 -3
- package/src/services/platformAuthService.ts +111 -40
|
@@ -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
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
style={
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
</
|
|
93
|
-
</
|
|
94
|
-
</
|
|
95
|
-
</
|
|
96
|
-
</
|
|
97
|
-
</
|
|
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.
|
|
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
|
-
|
|
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: '#
|
|
214
|
-
|
|
215
|
-
|
|
350
|
+
backgroundColor: '#000',
|
|
351
|
+
},
|
|
352
|
+
completeButtonDisabled: {
|
|
353
|
+
backgroundColor: '#E0E0E0',
|
|
216
354
|
},
|
|
217
355
|
completeButtonText: {
|
|
218
356
|
fontSize: 16,
|
|
219
357
|
fontWeight: '600',
|
|
220
|
-
color: '#
|
|
358
|
+
color: '#fff',
|
|
359
|
+
},
|
|
360
|
+
completeButtonTextDisabled: {
|
|
361
|
+
color: '#999',
|
|
221
362
|
},
|
|
222
363
|
});
|