@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.
- package/README.md +23 -3
- package/lib/commonjs/api/index.js +5 -1
- package/lib/commonjs/api/index.js.map +1 -1
- package/lib/commonjs/components/OnairosButton.js +5 -3
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/Overlay.js +274 -104
- package/lib/commonjs/components/Overlay.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +12 -0
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/components/onboarding/OAuthWebView.js +28 -9
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/components/onboarding/PlatformConnector.js +6 -1
- package/lib/commonjs/components/onboarding/PlatformConnector.js.map +1 -1
- package/lib/commonjs/components/screens/ConnectorScreen.js +3 -2
- package/lib/commonjs/components/screens/ConnectorScreen.js.map +1 -1
- package/lib/commonjs/constants/index.js +1 -1
- package/lib/commonjs/hooks/useConnections.js +77 -15
- package/lib/commonjs/hooks/useConnections.js.map +1 -1
- package/lib/commonjs/hooks/useCredentials.js +2 -0
- package/lib/commonjs/hooks/useCredentials.js.map +1 -1
- package/lib/commonjs/index.js +51 -56
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/services/oauthService.js +26 -51
- package/lib/commonjs/services/oauthService.js.map +1 -1
- package/lib/commonjs/types/ambient.d.js +2 -0
- package/lib/commonjs/types/ambient.d.js.map +1 -0
- package/lib/commonjs/types/node-fix.d.js +2 -0
- package/lib/commonjs/types/node-fix.d.js.map +1 -0
- package/lib/commonjs/types/node-override.d.js +2 -0
- package/lib/commonjs/types/node-override.d.js.map +1 -0
- package/lib/commonjs/types/types.d.js +2 -0
- package/lib/commonjs/types/types.d.js.map +1 -0
- package/lib/commonjs/utils/encryption.js +8 -2
- package/lib/commonjs/utils/encryption.js.map +1 -1
- package/lib/commonjs/utils/secureStorage.js +23 -4
- package/lib/commonjs/utils/secureStorage.js.map +1 -1
- package/lib/module/api/index.js +5 -1
- package/lib/module/api/index.js.map +1 -1
- package/lib/module/components/OnairosButton.js +6 -4
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/Overlay.js +275 -107
- package/lib/module/components/Overlay.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +12 -0
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +28 -9
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/components/onboarding/PlatformConnector.js +6 -1
- package/lib/module/components/onboarding/PlatformConnector.js.map +1 -1
- package/lib/module/components/screens/ConnectorScreen.js +3 -2
- package/lib/module/components/screens/ConnectorScreen.js.map +1 -1
- package/lib/module/constants/index.js +1 -1
- package/lib/module/hooks/useConnections.js +77 -14
- package/lib/module/hooks/useConnections.js.map +1 -1
- package/lib/module/hooks/useCredentials.js +2 -0
- package/lib/module/hooks/useCredentials.js.map +1 -1
- package/lib/module/index.js +27 -9
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/oauthService.js +26 -33
- package/lib/module/services/oauthService.js.map +1 -1
- package/lib/module/types/ambient.d.js +2 -0
- package/lib/module/types/ambient.d.js.map +1 -0
- package/lib/module/types/node-fix.d.js +2 -0
- package/lib/module/types/node-fix.d.js.map +1 -0
- package/lib/module/types/node-override.d.js +2 -0
- package/lib/module/types/node-override.d.js.map +1 -0
- package/lib/module/types/types.d.js +2 -0
- package/lib/module/types/types.d.js.map +1 -0
- package/lib/module/utils/encryption.js +8 -2
- package/lib/module/utils/encryption.js.map +1 -1
- package/lib/module/utils/secureStorage.js +23 -3
- package/lib/module/utils/secureStorage.js.map +1 -1
- package/lib/typescript/api/index.d.ts +8 -0
- package/lib/typescript/api/index.d.ts.map +1 -0
- package/lib/typescript/components/DataRequestModal.d.ts +11 -0
- package/lib/typescript/components/DataRequestModal.d.ts.map +1 -0
- package/lib/typescript/components/Onairos.d.ts +29 -0
- package/lib/typescript/components/Onairos.d.ts.map +1 -0
- package/lib/typescript/components/OnairosButton.d.ts +7 -0
- package/lib/typescript/components/OnairosButton.d.ts.map +1 -0
- package/lib/typescript/components/Overlay.d.ts +18 -0
- package/lib/typescript/components/Overlay.d.ts.map +1 -0
- package/lib/typescript/components/PinInput.d.ts +4 -0
- package/lib/typescript/components/PinInput.d.ts.map +1 -0
- package/lib/typescript/components/PlatformList.d.ts +4 -0
- package/lib/typescript/components/PlatformList.d.ts.map +1 -0
- package/lib/typescript/components/TrainingModal.d.ts +4 -0
- package/lib/typescript/components/TrainingModal.d.ts.map +1 -0
- package/lib/typescript/components/UniversalOnboarding.d.ts +4 -0
- package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -0
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts +4 -0
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -0
- package/lib/typescript/components/onboarding/OnboardingHeader.d.ts +11 -0
- package/lib/typescript/components/onboarding/OnboardingHeader.d.ts.map +1 -0
- package/lib/typescript/components/onboarding/PinInput.d.ts +4 -0
- package/lib/typescript/components/onboarding/PinInput.d.ts.map +1 -0
- package/lib/typescript/components/onboarding/PlatformConnector.d.ts +13 -0
- package/lib/typescript/components/onboarding/PlatformConnector.d.ts.map +1 -0
- package/lib/typescript/components/screens/ConnectorScreen.d.ts +9 -0
- package/lib/typescript/components/screens/ConnectorScreen.d.ts.map +1 -0
- package/lib/typescript/components/screens/LoadingScreen.d.ts +9 -0
- package/lib/typescript/components/screens/LoadingScreen.d.ts.map +1 -0
- package/lib/typescript/components/screens/PinCreationScreen.d.ts +10 -0
- package/lib/typescript/components/screens/PinCreationScreen.d.ts.map +1 -0
- package/lib/typescript/constants/index.d.ts +52 -0
- package/lib/typescript/constants/index.d.ts.map +1 -0
- package/lib/typescript/hooks/useConnections.d.ts +9 -0
- package/lib/typescript/hooks/useConnections.d.ts.map +1 -0
- package/lib/typescript/hooks/useCredentials.d.ts +9 -0
- package/lib/typescript/hooks/useCredentials.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +45 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/services/oauthService.d.ts +50 -0
- package/lib/typescript/services/oauthService.d.ts.map +1 -0
- package/lib/typescript/types/index.d.ts +145 -0
- package/lib/typescript/types/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +135 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/utils/api.d.ts +6 -0
- package/lib/typescript/utils/api.d.ts.map +1 -0
- package/lib/typescript/utils/auth.d.ts +6 -0
- package/lib/typescript/utils/auth.d.ts.map +1 -0
- package/lib/typescript/utils/crypto.d.ts +4 -0
- package/lib/typescript/utils/crypto.d.ts.map +1 -0
- package/lib/typescript/utils/debugHelper.d.ts +29 -0
- package/lib/typescript/utils/debugHelper.d.ts.map +1 -0
- package/lib/typescript/utils/encryption.d.ts +19 -0
- package/lib/typescript/utils/encryption.d.ts.map +1 -0
- package/lib/typescript/utils/onairosApi.d.ts +72 -0
- package/lib/typescript/utils/onairosApi.d.ts.map +1 -0
- package/lib/typescript/utils/secureStorage.d.ts +63 -0
- package/lib/typescript/utils/secureStorage.d.ts.map +1 -0
- package/package.json +16 -4
- package/src/api/index.ts +11 -11
- package/src/components/OnairosButton.tsx +5 -3
- package/src/components/Overlay.tsx +319 -135
- package/src/components/UniversalOnboarding.tsx +12 -0
- package/src/components/onboarding/OAuthWebView.tsx +27 -7
- package/src/components/onboarding/PlatformConnector.tsx +5 -0
- package/src/components/screens/ConnectorScreen.tsx +3 -2
- package/src/constants/index.ts +81 -81
- package/src/hooks/useConnections.ts +76 -16
- package/src/hooks/useCredentials.ts +5 -1
- package/src/index.ts +29 -1
- package/src/services/oauthService.ts +412 -419
- package/src/types/ambient.d.ts +29 -0
- package/src/types/index.d.ts +48 -8
- package/src/types/index.ts +21 -15
- package/src/types/node-fix.d.ts +19 -0
- package/src/types/node-override.d.ts +24 -0
- package/src/types/types.d.ts +18 -0
- package/src/types.ts +121 -1
- package/src/utils/encryption.ts +7 -2
- package/src/utils/secureStorage.ts +25 -9
- package/types/index.d.ts +210 -0
- 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
|
|
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
|
|
40
|
-
const
|
|
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
|
-
//
|
|
57
|
+
// Expand the bottom sheet when component mounts
|
|
52
58
|
setTimeout(() => {
|
|
53
|
-
bottomSheetRef.current?.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
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, {
|
|
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
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
</TouchableOpacity>
|
|
170
|
-
</View>
|
|
171
|
-
))}
|
|
172
|
-
</ScrollView>
|
|
233
|
+
)}
|
|
234
|
+
</View>
|
|
235
|
+
</TouchableOpacity>
|
|
236
|
+
</View>
|
|
237
|
+
))}
|
|
238
|
+
</ScrollView>
|
|
173
239
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
</
|
|
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:
|
|
200
|
-
width: SCREEN_WIDTH,
|
|
296
|
+
backgroundColor: '#fff',
|
|
201
297
|
},
|
|
202
|
-
|
|
203
|
-
backgroundColor: '#
|
|
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: '
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
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
|
-
|
|
219
|
-
|
|
334
|
+
marginHorizontal: 16,
|
|
335
|
+
color: '#666',
|
|
220
336
|
},
|
|
221
|
-
|
|
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:
|
|
224
|
-
|
|
350
|
+
color: '#000',
|
|
351
|
+
},
|
|
352
|
+
appName: {
|
|
353
|
+
fontSize: 16,
|
|
354
|
+
color: '#666',
|
|
355
|
+
},
|
|
356
|
+
darkSubText: {
|
|
357
|
+
color: '#999',
|
|
225
358
|
},
|
|
226
|
-
|
|
227
|
-
fontSize:
|
|
228
|
-
color:
|
|
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:
|
|
368
|
+
padding: 24,
|
|
233
369
|
},
|
|
234
370
|
card: {
|
|
235
|
-
backgroundColor:
|
|
236
|
-
borderRadius:
|
|
237
|
-
marginBottom:
|
|
238
|
-
|
|
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.
|
|
241
|
-
shadowRadius:
|
|
242
|
-
elevation:
|
|
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: '
|
|
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:
|
|
396
|
+
borderColor: '#2196F3',
|
|
255
397
|
marginRight: 12,
|
|
398
|
+
marginTop: 2,
|
|
399
|
+
},
|
|
400
|
+
darkCheckbox: {
|
|
401
|
+
borderColor: '#2196F3',
|
|
256
402
|
},
|
|
257
403
|
checkboxSelected: {
|
|
258
|
-
backgroundColor:
|
|
404
|
+
backgroundColor: '#2196F3',
|
|
259
405
|
},
|
|
260
406
|
cardContent: {
|
|
261
407
|
flex: 1,
|
|
262
408
|
},
|
|
263
409
|
cardTitle: {
|
|
264
|
-
fontSize:
|
|
265
|
-
fontWeight: '
|
|
410
|
+
fontSize: 16,
|
|
411
|
+
fontWeight: '600',
|
|
266
412
|
marginBottom: 4,
|
|
413
|
+
color: '#333',
|
|
267
414
|
},
|
|
268
415
|
cardDescription: {
|
|
269
416
|
fontSize: 14,
|
|
270
|
-
color:
|
|
271
|
-
marginBottom:
|
|
417
|
+
color: '#666',
|
|
418
|
+
marginBottom: 6,
|
|
272
419
|
},
|
|
273
420
|
cardReward: {
|
|
274
421
|
fontSize: 14,
|
|
275
|
-
color:
|
|
276
|
-
fontWeight: '
|
|
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
|
-
|
|
431
|
+
justifyContent: 'space-between',
|
|
432
|
+
padding: 24,
|
|
283
433
|
borderTopWidth: 1,
|
|
284
|
-
borderTopColor:
|
|
434
|
+
borderTopColor: '#eee',
|
|
435
|
+
backgroundColor: '#fff',
|
|
285
436
|
},
|
|
286
|
-
|
|
437
|
+
darkFooter: {
|
|
438
|
+
backgroundColor: '#2A2A2A',
|
|
439
|
+
borderTopColor: '#333',
|
|
440
|
+
},
|
|
441
|
+
footerButtonCancel: {
|
|
287
442
|
paddingVertical: 8,
|
|
288
443
|
paddingHorizontal: 16,
|
|
289
|
-
|
|
290
|
-
|
|
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:
|
|
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:
|
|
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('
|
|
20
|
-
//
|
|
21
|
-
|
|
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={() =>
|
|
72
|
+
renderLoading={() => <View />}
|
|
53
73
|
style={styles.webView}
|
|
54
74
|
/>
|
|
55
75
|
|