@onairos/react-native 3.0.2 → 3.0.5

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 (155) hide show
  1. package/README.md +23 -3
  2. package/lib/commonjs/api/index.js +5 -1
  3. package/lib/commonjs/api/index.js.map +1 -1
  4. package/lib/commonjs/components/OnairosButton.js +5 -3
  5. package/lib/commonjs/components/OnairosButton.js.map +1 -1
  6. package/lib/commonjs/components/Overlay.js +274 -104
  7. package/lib/commonjs/components/Overlay.js.map +1 -1
  8. package/lib/commonjs/components/UniversalOnboarding.js +12 -0
  9. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  10. package/lib/commonjs/components/onboarding/OAuthWebView.js +28 -9
  11. package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
  12. package/lib/commonjs/components/onboarding/PlatformConnector.js +6 -1
  13. package/lib/commonjs/components/onboarding/PlatformConnector.js.map +1 -1
  14. package/lib/commonjs/components/screens/ConnectorScreen.js +3 -2
  15. package/lib/commonjs/components/screens/ConnectorScreen.js.map +1 -1
  16. package/lib/commonjs/constants/index.js +1 -1
  17. package/lib/commonjs/hooks/useConnections.js +77 -15
  18. package/lib/commonjs/hooks/useConnections.js.map +1 -1
  19. package/lib/commonjs/hooks/useCredentials.js +2 -0
  20. package/lib/commonjs/hooks/useCredentials.js.map +1 -1
  21. package/lib/commonjs/index.js +51 -56
  22. package/lib/commonjs/index.js.map +1 -1
  23. package/lib/commonjs/services/oauthService.js +26 -51
  24. package/lib/commonjs/services/oauthService.js.map +1 -1
  25. package/lib/commonjs/types/ambient.d.js +2 -0
  26. package/lib/commonjs/types/ambient.d.js.map +1 -0
  27. package/lib/commonjs/types/node-fix.d.js +2 -0
  28. package/lib/commonjs/types/node-fix.d.js.map +1 -0
  29. package/lib/commonjs/types/node-override.d.js +2 -0
  30. package/lib/commonjs/types/node-override.d.js.map +1 -0
  31. package/lib/commonjs/types/types.d.js +2 -0
  32. package/lib/commonjs/types/types.d.js.map +1 -0
  33. package/lib/commonjs/utils/encryption.js +8 -2
  34. package/lib/commonjs/utils/encryption.js.map +1 -1
  35. package/lib/commonjs/utils/secureStorage.js +23 -4
  36. package/lib/commonjs/utils/secureStorage.js.map +1 -1
  37. package/lib/module/api/index.js +5 -1
  38. package/lib/module/api/index.js.map +1 -1
  39. package/lib/module/components/OnairosButton.js +6 -4
  40. package/lib/module/components/OnairosButton.js.map +1 -1
  41. package/lib/module/components/Overlay.js +275 -107
  42. package/lib/module/components/Overlay.js.map +1 -1
  43. package/lib/module/components/UniversalOnboarding.js +12 -0
  44. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  45. package/lib/module/components/onboarding/OAuthWebView.js +28 -9
  46. package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
  47. package/lib/module/components/onboarding/PlatformConnector.js +6 -1
  48. package/lib/module/components/onboarding/PlatformConnector.js.map +1 -1
  49. package/lib/module/components/screens/ConnectorScreen.js +3 -2
  50. package/lib/module/components/screens/ConnectorScreen.js.map +1 -1
  51. package/lib/module/constants/index.js +1 -1
  52. package/lib/module/hooks/useConnections.js +77 -14
  53. package/lib/module/hooks/useConnections.js.map +1 -1
  54. package/lib/module/hooks/useCredentials.js +2 -0
  55. package/lib/module/hooks/useCredentials.js.map +1 -1
  56. package/lib/module/index.js +27 -9
  57. package/lib/module/index.js.map +1 -1
  58. package/lib/module/services/oauthService.js +26 -33
  59. package/lib/module/services/oauthService.js.map +1 -1
  60. package/lib/module/types/ambient.d.js +2 -0
  61. package/lib/module/types/ambient.d.js.map +1 -0
  62. package/lib/module/types/node-fix.d.js +2 -0
  63. package/lib/module/types/node-fix.d.js.map +1 -0
  64. package/lib/module/types/node-override.d.js +2 -0
  65. package/lib/module/types/node-override.d.js.map +1 -0
  66. package/lib/module/types/types.d.js +2 -0
  67. package/lib/module/types/types.d.js.map +1 -0
  68. package/lib/module/utils/encryption.js +8 -2
  69. package/lib/module/utils/encryption.js.map +1 -1
  70. package/lib/module/utils/secureStorage.js +23 -3
  71. package/lib/module/utils/secureStorage.js.map +1 -1
  72. package/lib/typescript/api/index.d.ts +8 -0
  73. package/lib/typescript/api/index.d.ts.map +1 -0
  74. package/lib/typescript/components/DataRequestModal.d.ts +11 -0
  75. package/lib/typescript/components/DataRequestModal.d.ts.map +1 -0
  76. package/lib/typescript/components/Onairos.d.ts +29 -0
  77. package/lib/typescript/components/Onairos.d.ts.map +1 -0
  78. package/lib/typescript/components/OnairosButton.d.ts +7 -0
  79. package/lib/typescript/components/OnairosButton.d.ts.map +1 -0
  80. package/lib/typescript/components/Overlay.d.ts +18 -0
  81. package/lib/typescript/components/Overlay.d.ts.map +1 -0
  82. package/lib/typescript/components/PinInput.d.ts +4 -0
  83. package/lib/typescript/components/PinInput.d.ts.map +1 -0
  84. package/lib/typescript/components/PlatformList.d.ts +4 -0
  85. package/lib/typescript/components/PlatformList.d.ts.map +1 -0
  86. package/lib/typescript/components/TrainingModal.d.ts +4 -0
  87. package/lib/typescript/components/TrainingModal.d.ts.map +1 -0
  88. package/lib/typescript/components/UniversalOnboarding.d.ts +4 -0
  89. package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -0
  90. package/lib/typescript/components/onboarding/OAuthWebView.d.ts +4 -0
  91. package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -0
  92. package/lib/typescript/components/onboarding/OnboardingHeader.d.ts +11 -0
  93. package/lib/typescript/components/onboarding/OnboardingHeader.d.ts.map +1 -0
  94. package/lib/typescript/components/onboarding/PinInput.d.ts +4 -0
  95. package/lib/typescript/components/onboarding/PinInput.d.ts.map +1 -0
  96. package/lib/typescript/components/onboarding/PlatformConnector.d.ts +13 -0
  97. package/lib/typescript/components/onboarding/PlatformConnector.d.ts.map +1 -0
  98. package/lib/typescript/components/screens/ConnectorScreen.d.ts +9 -0
  99. package/lib/typescript/components/screens/ConnectorScreen.d.ts.map +1 -0
  100. package/lib/typescript/components/screens/LoadingScreen.d.ts +9 -0
  101. package/lib/typescript/components/screens/LoadingScreen.d.ts.map +1 -0
  102. package/lib/typescript/components/screens/PinCreationScreen.d.ts +10 -0
  103. package/lib/typescript/components/screens/PinCreationScreen.d.ts.map +1 -0
  104. package/lib/typescript/constants/index.d.ts +52 -0
  105. package/lib/typescript/constants/index.d.ts.map +1 -0
  106. package/lib/typescript/hooks/useConnections.d.ts +9 -0
  107. package/lib/typescript/hooks/useConnections.d.ts.map +1 -0
  108. package/lib/typescript/hooks/useCredentials.d.ts +9 -0
  109. package/lib/typescript/hooks/useCredentials.d.ts.map +1 -0
  110. package/lib/typescript/index.d.ts +45 -0
  111. package/lib/typescript/index.d.ts.map +1 -0
  112. package/lib/typescript/services/oauthService.d.ts +50 -0
  113. package/lib/typescript/services/oauthService.d.ts.map +1 -0
  114. package/lib/typescript/types/index.d.ts +145 -0
  115. package/lib/typescript/types/index.d.ts.map +1 -0
  116. package/lib/typescript/types.d.ts +135 -0
  117. package/lib/typescript/types.d.ts.map +1 -0
  118. package/lib/typescript/utils/api.d.ts +6 -0
  119. package/lib/typescript/utils/api.d.ts.map +1 -0
  120. package/lib/typescript/utils/auth.d.ts +6 -0
  121. package/lib/typescript/utils/auth.d.ts.map +1 -0
  122. package/lib/typescript/utils/crypto.d.ts +4 -0
  123. package/lib/typescript/utils/crypto.d.ts.map +1 -0
  124. package/lib/typescript/utils/debugHelper.d.ts +29 -0
  125. package/lib/typescript/utils/debugHelper.d.ts.map +1 -0
  126. package/lib/typescript/utils/encryption.d.ts +19 -0
  127. package/lib/typescript/utils/encryption.d.ts.map +1 -0
  128. package/lib/typescript/utils/onairosApi.d.ts +72 -0
  129. package/lib/typescript/utils/onairosApi.d.ts.map +1 -0
  130. package/lib/typescript/utils/secureStorage.d.ts +63 -0
  131. package/lib/typescript/utils/secureStorage.d.ts.map +1 -0
  132. package/package.json +16 -4
  133. package/src/api/index.ts +11 -11
  134. package/src/components/OnairosButton.tsx +5 -3
  135. package/src/components/Overlay.tsx +319 -135
  136. package/src/components/UniversalOnboarding.tsx +12 -0
  137. package/src/components/onboarding/OAuthWebView.tsx +27 -7
  138. package/src/components/onboarding/PlatformConnector.tsx +5 -0
  139. package/src/components/screens/ConnectorScreen.tsx +3 -2
  140. package/src/constants/index.ts +81 -81
  141. package/src/hooks/useConnections.ts +76 -16
  142. package/src/hooks/useCredentials.ts +5 -1
  143. package/src/index.ts +29 -1
  144. package/src/services/oauthService.ts +412 -419
  145. package/src/types/ambient.d.ts +29 -0
  146. package/src/types/index.d.ts +48 -8
  147. package/src/types/index.ts +21 -15
  148. package/src/types/node-fix.d.ts +19 -0
  149. package/src/types/node-override.d.ts +24 -0
  150. package/src/types/types.d.ts +18 -0
  151. package/src/types.ts +121 -1
  152. package/src/utils/encryption.ts +7 -2
  153. package/src/utils/secureStorage.ts +25 -9
  154. package/types/index.d.ts +210 -0
  155. package/types/node-env.d.ts +15 -0
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, useRef } from 'react';
1
+ import React, { useState, useEffect, useRef, useCallback } from 'react';
2
2
  import {
3
3
  View,
4
4
  Text,
@@ -8,8 +8,9 @@ import {
8
8
  Alert,
9
9
  Platform,
10
10
  Dimensions,
11
+ Modal,
11
12
  } from 'react-native';
12
- import { BottomSheetModal, BottomSheetBackdrop } from '@gorhom/bottom-sheet';
13
+ import BottomSheet from '@gorhom/bottom-sheet';
13
14
  // import DeviceInfo from 'react-native-device-info'; // Comment out device info import
14
15
  import { COLORS } from '../constants';
15
16
  import { onairosApi } from '../api';
@@ -26,6 +27,8 @@ interface OverlayProps {
26
27
  username: string;
27
28
  modelKey: string;
28
29
  onResolved: (apiUrl: string, accessToken: string, loginDetails: any) => void;
30
+ appName?: string;
31
+ darkMode?: boolean;
29
32
  }
30
33
 
31
34
  export const Overlay: React.FC<OverlayProps> = ({
@@ -33,11 +36,14 @@ export const Overlay: React.FC<OverlayProps> = ({
33
36
  username,
34
37
  modelKey,
35
38
  onResolved,
39
+ appName = 'Your App',
40
+ darkMode = false,
36
41
  }) => {
37
42
  const [selections, setSelections] = useState<{ [key: string]: boolean }>({});
38
43
  const [details, setDetails] = useState<string>('');
39
- const bottomSheetRef = useRef<BottomSheetModal>(null);
40
- const snapPoints = ['60%']; // Set to 60% of screen height
44
+ const [visible, setVisible] = useState(true);
45
+ const bottomSheetRef = useRef<BottomSheet>(null);
46
+ const snapPoints = useRef(['80%']);
41
47
 
42
48
  useEffect(() => {
43
49
  // Initialize selection state
@@ -48,30 +54,45 @@ export const Overlay: React.FC<OverlayProps> = ({
48
54
  setSelections(initialSelections);
49
55
  getDetails();
50
56
 
51
- // Present the bottom sheet when component mounts
57
+ // Expand the bottom sheet when component mounts
52
58
  setTimeout(() => {
53
- bottomSheetRef.current?.present();
59
+ bottomSheetRef.current?.expand();
54
60
  }, 100);
55
61
  }, []);
56
62
 
57
63
  const getDetails = async () => {
58
64
  try {
65
+ // In Expo or development, use mock data
66
+ if (__DEV__) {
67
+ setDetails('Development mode - mock account info');
68
+ return;
69
+ }
70
+
59
71
  const response = await onairosApi.post('getAccountInfo', {
60
72
  Info: {
61
73
  username: username,
62
74
  },
63
75
  });
64
- setDetails(response.AccountInfo);
76
+ // Handle response data properly based on API structure
77
+ if (response && response.data) {
78
+ const accountInfo = typeof response.data === 'object' && response.data.AccountInfo
79
+ ? response.data.AccountInfo
80
+ : `User: ${username}`;
81
+ setDetails(accountInfo);
82
+ } else {
83
+ setDetails(`User: ${username}`);
84
+ }
65
85
  } catch (e) {
66
86
  console.error('Error getting account info:', e);
87
+ setDetails(`User: ${username}`);
67
88
  }
68
89
  };
69
90
 
70
- const closeOverlay = () => {
71
- bottomSheetRef.current?.dismiss();
72
- };
91
+ const closeOverlay = useCallback(() => {
92
+ setVisible(false);
93
+ }, []);
73
94
 
74
- const confirmSelection = async () => {
95
+ const confirmSelection = useCallback(async () => {
75
96
  try {
76
97
  // Mock app identifier
77
98
  const appId = Platform.select({
@@ -80,8 +101,36 @@ export const Overlay: React.FC<OverlayProps> = ({
80
101
  default: 'unknown'
81
102
  });
82
103
 
83
- const serverPublicKey = await getServerPublicKey();
84
- const encryptedModelKey = encryptModelKey(serverPublicKey, modelKey);
104
+ // In development mode, use mock data
105
+ if (__DEV__) {
106
+ onResolved('https://api2.onairos.uk', 'mock-token', {
107
+ username,
108
+ selections
109
+ });
110
+ closeOverlay();
111
+ return;
112
+ }
113
+
114
+ // Get server public key for encryption
115
+ let serverPublicKey = 'mock-key';
116
+ try {
117
+ const keyResponse = await onairosApi.get('public/key');
118
+ if (keyResponse && keyResponse.data && typeof keyResponse.data === 'object') {
119
+ serverPublicKey = keyResponse.data.publicKey || 'mock-key';
120
+ }
121
+ } catch (e) {
122
+ console.error('Error getting server public key:', e);
123
+ }
124
+
125
+ // Encrypt the model key - only if the function exists and server key is valid
126
+ let encryptedModelKey = modelKey;
127
+ if (typeof encryptModelKey === 'function' && serverPublicKey) {
128
+ try {
129
+ encryptedModelKey = encryptModelKey(serverPublicKey, modelKey);
130
+ } catch (e) {
131
+ console.error('Error encrypting model key:', e);
132
+ }
133
+ }
85
134
 
86
135
  const response = await onairosApi.post('getAPIUrlMobile', {
87
136
  Info: {
@@ -95,15 +144,35 @@ export const Overlay: React.FC<OverlayProps> = ({
95
144
  },
96
145
  });
97
146
 
98
- if (response.apiUrl && response.token) {
99
- onResolved(response.apiUrl, response.token, { username });
147
+ if (response.data?.apiUrl && response.data?.token) {
148
+ onResolved(response.data.apiUrl, response.data.token, {
149
+ username,
150
+ selections
151
+ });
152
+ closeOverlay();
153
+ } else {
154
+ // If response doesn't have expected format, use fallbacks
155
+ onResolved('https://api2.onairos.uk', 'fallback-token', {
156
+ username,
157
+ selections
158
+ });
100
159
  closeOverlay();
101
160
  }
102
161
  } catch (e) {
103
162
  console.error('Error confirming selection:', e);
104
- showErrorModal('Failed to confirm selection. Please try again.');
163
+ // In case of error, provide fallback (development mode)
164
+ if (__DEV__) {
165
+ onResolved('https://api2.onairos.uk', 'error-fallback-token', {
166
+ username,
167
+ selections,
168
+ error: true
169
+ });
170
+ closeOverlay();
171
+ } else {
172
+ showErrorModal('Failed to confirm selection. Please try again.');
173
+ }
105
174
  }
106
- };
175
+ }, [selections, username, modelKey, onResolved]);
107
176
 
108
177
  const showErrorModal = (errorMessage: string) => {
109
178
  Alert.alert('Notice', errorMessage, [{ text: 'OK' }]);
@@ -111,191 +180,306 @@ export const Overlay: React.FC<OverlayProps> = ({
111
180
 
112
181
  const selectedCount = Object.values(selections).filter(Boolean).length;
113
182
 
114
- return (
115
- <BottomSheetModal
116
- ref={bottomSheetRef}
117
- snapPoints={snapPoints}
118
- handleIndicatorStyle={styles.handleIndicator}
119
- backdropComponent={(props) => (
120
- <BottomSheetBackdrop
121
- {...props}
122
- appearsOnIndex={0}
123
- disappearsOnIndex={-1}
124
- opacity={0.7}
125
- />
126
- )}
127
- enablePanDownToClose={true}
128
- keyboardBehavior="interactive"
129
- keyboardBlurBehavior="restore"
130
- >
131
- <View style={styles.container}>
132
- <View style={styles.header}>
133
- <Text style={styles.headerTitle}>Onairos</Text>
134
- <TouchableOpacity onPress={closeOverlay}>
135
- <Text style={styles.closeButton}>×</Text>
136
- </TouchableOpacity>
137
- <Text style={styles.username}>{username}</Text>
183
+ // Render content of the bottom sheet
184
+ const renderContent = () => (
185
+ <View style={[styles.container, darkMode && styles.darkContainer]}>
186
+ <View style={[styles.header, darkMode && styles.darkHeader]}>
187
+ <View style={styles.headerContent}>
188
+ <View style={[styles.appIcon, darkMode && styles.darkAppIcon]}>
189
+ <Text style={[styles.appIconText, darkMode && styles.darkText]}>A</Text>
190
+ </View>
191
+ <Text style={[styles.arrow, darkMode && styles.darkArrow]}>→</Text>
192
+ <View style={[styles.onairosIcon, darkMode && styles.darkAppIcon]}>
193
+ <Text style={[styles.onairosIconText, darkMode && styles.darkText]}>O</Text>
194
+ </View>
138
195
  </View>
196
+ <Text style={[styles.appName, darkMode && styles.darkSubText]}>{appName}</Text>
197
+ </View>
139
198
 
140
- <ScrollView style={styles.content}>
141
- {Object.entries(data).map(([key, value]) => (
142
- <View key={key} style={styles.card}>
143
- <TouchableOpacity
144
- style={styles.checkboxContainer}
145
- onPress={() =>
146
- setSelections((prev) => ({
147
- ...prev,
148
- [key]: !prev[key],
149
- }))
150
- }
151
- >
152
- <View
153
- style={[
154
- styles.checkbox,
155
- selections[key] && styles.checkboxSelected,
156
- ]}
157
- />
158
- <View style={styles.cardContent}>
159
- <Text style={styles.cardTitle}>{value.type} Insight</Text>
160
- <Text style={styles.cardDescription}>
161
- Description: {value.descriptions}
199
+ <Text style={[styles.privacyMessage, darkMode && styles.darkSubText]}>
200
+ No one will ever see your raw app data
201
+ </Text>
202
+
203
+ <ScrollView style={styles.content}>
204
+ {Object.entries(data).map(([key, value]) => (
205
+ <View key={key} style={[styles.card, darkMode && styles.darkCard]}>
206
+ <TouchableOpacity
207
+ style={styles.checkboxContainer}
208
+ onPress={() =>
209
+ setSelections((prev) => ({
210
+ ...prev,
211
+ [key]: !prev[key],
212
+ }))
213
+ }
214
+ >
215
+ <View
216
+ style={[
217
+ styles.checkbox,
218
+ selections[key] && styles.checkboxSelected,
219
+ darkMode && styles.darkCheckbox,
220
+ ]}
221
+ />
222
+ <View style={styles.cardContent}>
223
+ <Text style={[styles.cardTitle, darkMode && styles.darkText]}>
224
+ {value.type} Insight
225
+ </Text>
226
+ <Text style={[styles.cardDescription, darkMode && styles.darkSubText]}>
227
+ {value.descriptions}
228
+ </Text>
229
+ {value.reward && (
230
+ <Text style={[styles.cardReward, darkMode && styles.darkReward]}>
231
+ Reward: {value.reward}
162
232
  </Text>
163
- {value.reward && (
164
- <Text style={styles.cardReward}>
165
- Reward: {value.reward}
166
- </Text>
167
- )}
168
- </View>
169
- </TouchableOpacity>
170
- </View>
171
- ))}
172
- </ScrollView>
233
+ )}
234
+ </View>
235
+ </TouchableOpacity>
236
+ </View>
237
+ ))}
238
+ </ScrollView>
173
239
 
174
- <View style={styles.footer}>
175
- <TouchableOpacity
176
- style={styles.footerButton}
177
- onPress={closeOverlay}
178
- >
179
- <Text style={styles.footerButtonText}>Cancel</Text>
180
- </TouchableOpacity>
181
- <Text style={styles.selectedCount}>Selected: {selectedCount}</Text>
182
- <TouchableOpacity
183
- style={styles.footerButton}
184
- onPress={confirmSelection}
185
- >
186
- <Text style={styles.footerButtonText}>Confirm</Text>
187
- </TouchableOpacity>
188
- </View>
240
+ <View style={[styles.footer, darkMode && styles.darkFooter]}>
241
+ <TouchableOpacity
242
+ style={[styles.footerButtonCancel, darkMode && styles.darkFooterButton]}
243
+ onPress={closeOverlay}
244
+ >
245
+ <Text style={[styles.footerButtonText, darkMode && styles.darkSubText]}>Cancel</Text>
246
+ </TouchableOpacity>
247
+ <Text style={[styles.selectedCount, darkMode && styles.darkSubText]}>
248
+ Selected: {selectedCount}
249
+ </Text>
250
+ <TouchableOpacity
251
+ style={[styles.footerButtonConfirm, darkMode && styles.darkFooterButtonConfirm]}
252
+ onPress={confirmSelection}
253
+ >
254
+ <Text style={[styles.footerButtonTextConfirm, darkMode && styles.darkText]}>
255
+ Confirm
256
+ </Text>
257
+ </TouchableOpacity>
258
+ </View>
259
+ </View>
260
+ );
261
+
262
+ // Main component rendering - Use Modal at the root level
263
+ return (
264
+ <Modal
265
+ visible={visible}
266
+ animationType="fade"
267
+ transparent={true}
268
+ onRequestClose={closeOverlay}
269
+ >
270
+ <View style={styles.modalContainer}>
271
+ <BottomSheet
272
+ ref={bottomSheetRef}
273
+ snapPoints={snapPoints.current}
274
+ enablePanDownToClose
275
+ onClose={closeOverlay}
276
+ backgroundStyle={darkMode ? styles.darkBackground : styles.lightBackground}
277
+ handleIndicatorStyle={darkMode ? styles.darkHandle : styles.lightHandle}
278
+ index={0}
279
+ >
280
+ {renderContent()}
281
+ </BottomSheet>
189
282
  </View>
190
- </BottomSheetModal>
283
+ </Modal>
191
284
  );
192
285
  };
193
286
 
194
- const { width: SCREEN_WIDTH } = Dimensions.get('window');
287
+ const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
195
288
 
196
289
  const styles = StyleSheet.create({
290
+ modalContainer: {
291
+ flex: 1,
292
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
293
+ },
197
294
  container: {
198
295
  flex: 1,
199
- backgroundColor: COLORS.white,
200
- width: SCREEN_WIDTH,
296
+ backgroundColor: '#fff',
201
297
  },
202
- handleIndicator: {
203
- backgroundColor: '#999',
204
- width: 40,
205
- height: 5,
298
+ darkContainer: {
299
+ backgroundColor: '#1A1A1A',
206
300
  },
207
301
  header: {
302
+ padding: 24,
303
+ alignItems: 'center',
304
+ },
305
+ darkHeader: {
306
+ backgroundColor: '#1A1A1A',
307
+ },
308
+ headerContent: {
208
309
  flexDirection: 'row',
209
310
  alignItems: 'center',
210
- justifyContent: 'space-between',
211
- padding: 16,
212
- backgroundColor: COLORS.primary,
213
- borderTopLeftRadius: 10,
214
- borderTopRightRadius: 10,
311
+ justifyContent: 'center',
312
+ marginBottom: 16,
313
+ },
314
+ appIcon: {
315
+ width: 48,
316
+ height: 48,
317
+ borderRadius: 16,
318
+ backgroundColor: '#F5F5F5',
319
+ alignItems: 'center',
320
+ justifyContent: 'center',
215
321
  },
216
- headerTitle: {
322
+ darkAppIcon: {
323
+ backgroundColor: '#2A2A2A',
324
+ },
325
+ appIconText: {
326
+ fontSize: 24,
327
+ color: '#000',
328
+ },
329
+ darkText: {
330
+ color: '#fff',
331
+ },
332
+ arrow: {
217
333
  fontSize: 24,
218
- color: COLORS.white,
219
- fontWeight: 'bold',
334
+ marginHorizontal: 16,
335
+ color: '#666',
220
336
  },
221
- closeButton: {
337
+ darkArrow: {
338
+ color: '#999',
339
+ },
340
+ onairosIcon: {
341
+ width: 48,
342
+ height: 48,
343
+ borderRadius: 16,
344
+ backgroundColor: '#F5F5F5',
345
+ alignItems: 'center',
346
+ justifyContent: 'center',
347
+ },
348
+ onairosIconText: {
222
349
  fontSize: 24,
223
- color: COLORS.white,
224
- padding: 8,
350
+ color: '#000',
351
+ },
352
+ appName: {
353
+ fontSize: 16,
354
+ color: '#666',
355
+ },
356
+ darkSubText: {
357
+ color: '#999',
225
358
  },
226
- username: {
227
- fontSize: 18,
228
- color: COLORS.white,
359
+ privacyMessage: {
360
+ fontSize: 14,
361
+ color: '#666',
362
+ textAlign: 'center',
363
+ fontStyle: 'italic',
364
+ marginBottom: 16,
229
365
  },
230
366
  content: {
231
367
  flex: 1,
232
- padding: 16,
368
+ padding: 24,
233
369
  },
234
370
  card: {
235
- backgroundColor: COLORS.white,
236
- borderRadius: 8,
237
- marginBottom: 12,
238
- shadowColor: COLORS.black,
371
+ backgroundColor: '#fff',
372
+ borderRadius: 20,
373
+ marginBottom: 16,
374
+ borderWidth: 1,
375
+ borderColor: '#eee',
376
+ shadowColor: '#000',
239
377
  shadowOffset: { width: 0, height: 2 },
240
- shadowOpacity: 0.1,
241
- shadowRadius: 4,
242
- elevation: 3,
378
+ shadowOpacity: 0.05,
379
+ shadowRadius: 8,
380
+ elevation: 2,
381
+ },
382
+ darkCard: {
383
+ backgroundColor: '#2A2A2A',
384
+ borderColor: '#333',
243
385
  },
244
386
  checkboxContainer: {
245
387
  flexDirection: 'row',
246
388
  padding: 16,
247
- alignItems: 'center',
389
+ alignItems: 'flex-start',
248
390
  },
249
391
  checkbox: {
250
392
  width: 24,
251
393
  height: 24,
252
394
  borderRadius: 4,
253
395
  borderWidth: 2,
254
- borderColor: COLORS.primary,
396
+ borderColor: '#2196F3',
255
397
  marginRight: 12,
398
+ marginTop: 2,
399
+ },
400
+ darkCheckbox: {
401
+ borderColor: '#2196F3',
256
402
  },
257
403
  checkboxSelected: {
258
- backgroundColor: COLORS.primary,
404
+ backgroundColor: '#2196F3',
259
405
  },
260
406
  cardContent: {
261
407
  flex: 1,
262
408
  },
263
409
  cardTitle: {
264
- fontSize: 18,
265
- fontWeight: 'bold',
410
+ fontSize: 16,
411
+ fontWeight: '600',
266
412
  marginBottom: 4,
413
+ color: '#333',
267
414
  },
268
415
  cardDescription: {
269
416
  fontSize: 14,
270
- color: COLORS.gray,
271
- marginBottom: 4,
417
+ color: '#666',
418
+ marginBottom: 6,
272
419
  },
273
420
  cardReward: {
274
421
  fontSize: 14,
275
- color: COLORS.success,
276
- fontWeight: 'bold',
422
+ color: '#4CAF50',
423
+ fontWeight: '500',
424
+ },
425
+ darkReward: {
426
+ color: '#81C784',
277
427
  },
278
428
  footer: {
279
429
  flexDirection: 'row',
280
- justifyContent: 'space-between',
281
430
  alignItems: 'center',
282
- padding: 16,
431
+ justifyContent: 'space-between',
432
+ padding: 24,
283
433
  borderTopWidth: 1,
284
- borderTopColor: COLORS.lightGray,
434
+ borderTopColor: '#eee',
435
+ backgroundColor: '#fff',
285
436
  },
286
- footerButton: {
437
+ darkFooter: {
438
+ backgroundColor: '#2A2A2A',
439
+ borderTopColor: '#333',
440
+ },
441
+ footerButtonCancel: {
287
442
  paddingVertical: 8,
288
443
  paddingHorizontal: 16,
289
- borderRadius: 8,
290
- backgroundColor: COLORS.primary,
444
+ },
445
+ darkFooterButton: {
446
+ backgroundColor: 'transparent',
447
+ },
448
+ footerButtonConfirm: {
449
+ paddingVertical: 16,
450
+ paddingHorizontal: 32,
451
+ borderRadius: 16,
452
+ backgroundColor: '#fff',
453
+ borderWidth: 1,
454
+ borderColor: '#000',
455
+ },
456
+ darkFooterButtonConfirm: {
457
+ backgroundColor: '#fff',
458
+ borderColor: '#fff',
291
459
  },
292
460
  footerButtonText: {
293
- color: COLORS.white,
461
+ color: '#666',
462
+ fontSize: 16,
463
+ },
464
+ footerButtonTextConfirm: {
465
+ color: '#000',
294
466
  fontSize: 16,
295
467
  fontWeight: '600',
296
468
  },
297
469
  selectedCount: {
298
470
  fontSize: 16,
299
- color: COLORS.gray,
471
+ color: '#666',
472
+ },
473
+ lightBackground: {
474
+ backgroundColor: '#fff',
475
+ },
476
+ darkBackground: {
477
+ backgroundColor: '#1A1A1A',
478
+ },
479
+ lightHandle: {
480
+ backgroundColor: '#ccc',
481
+ },
482
+ darkHandle: {
483
+ backgroundColor: '#666',
300
484
  },
301
485
  });
@@ -150,6 +150,18 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
150
150
  case 'training':
151
151
  return (
152
152
  <TrainingModal
153
+ visible={step === 'training'}
154
+ onClose={onClose}
155
+ onComplete={() => {
156
+ onComplete('https://api2.onairos.uk', 'dummy-token', {
157
+ pin,
158
+ connections,
159
+ selectedTier,
160
+ tierData: requestData?.[selectedTier],
161
+ });
162
+ }}
163
+ modelKey="onairosTrainingModel"
164
+ username="demo_user"
153
165
  progress={training.progress}
154
166
  eta={training.eta}
155
167
  onCancel={onClose}
@@ -10,25 +10,45 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
10
10
  platform,
11
11
  onComplete,
12
12
  onClose,
13
+ onSuccess,
13
14
  }) => {
14
15
  const [loading, setLoading] = useState(true);
15
16
 
16
17
  const handleNavigationStateChange = useCallback(
17
18
  (navState: WebViewNavigation) => {
18
19
  // Check if the URL includes our redirect URI
19
- if (navState.url.startsWith('onairosreact://auth/')) {
20
- // OAuth flow is complete - callback will be handled by the deep link handler
21
- onComplete();
20
+ if (navState.url.startsWith('onairosanime://auth/')) {
21
+ // Extract the authorization code from the URL
22
+ const authCode = extractAuthCode(navState.url);
23
+ if (authCode) {
24
+ onSuccess(authCode);
25
+ }
26
+
27
+ // OAuth flow is complete
28
+ if (onComplete) {
29
+ onComplete();
30
+ }
22
31
  return;
23
32
  }
24
33
  },
25
- [onComplete]
34
+ [onComplete, onSuccess]
26
35
  );
27
36
 
28
37
  const handleLoadEnd = useCallback(() => {
29
38
  setLoading(false);
30
39
  }, []);
31
40
 
41
+ // Extract auth code from redirect URL
42
+ const extractAuthCode = (redirectUrl: string): string => {
43
+ try {
44
+ const url = new URL(redirectUrl);
45
+ return url.searchParams.get('code') || '';
46
+ } catch (error) {
47
+ console.error('Error extracting auth code:', error);
48
+ return '';
49
+ }
50
+ };
51
+
32
52
  return (
33
53
  <SafeAreaView style={styles.container}>
34
54
  <View style={styles.header}>
@@ -37,9 +57,9 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
37
57
  </TouchableOpacity>
38
58
  <View style={styles.titleContainer}>
39
59
  <Icon
40
- name={getPlatformIcon(platform)}
60
+ name={getPlatformIcon(platform || 'default')}
41
61
  size={20}
42
- color={getPlatformColor(platform)}
62
+ color={getPlatformColor(platform || 'default')}
43
63
  />
44
64
  </View>
45
65
  </View>
@@ -49,7 +69,7 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
49
69
  onNavigationStateChange={handleNavigationStateChange}
50
70
  onLoadEnd={handleLoadEnd}
51
71
  startInLoadingState={true}
52
- renderLoading={() => null} // We'll handle our own loading UI
72
+ renderLoading={() => <View />}
53
73
  style={styles.webView}
54
74
  />
55
75