@onairos/react-native 3.0.16 → 3.0.17

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.
@@ -11,10 +11,11 @@ import {
11
11
  Modal,
12
12
  Animated,
13
13
  TouchableWithoutFeedback,
14
- StatusBar,
15
- KeyboardAvoidingView,
16
14
  SafeAreaView,
15
+ Image,
16
+ Switch,
17
17
  } from 'react-native';
18
+ import Icon from 'react-native-vector-icons/MaterialIcons';
18
19
  import { onairosApi } from '../api';
19
20
  import { encryptModelKey } from '../utils/encryption';
20
21
  import { COLORS } from '../constants';
@@ -34,6 +35,7 @@ interface OverlayProps {
34
35
  onResolved: (apiUrl: string, accessToken: string, loginDetails: any) => void;
35
36
  appName?: string;
36
37
  darkMode?: boolean;
38
+ platforms?: Array<{id: string, name: string, icon: any}>;
37
39
  }
38
40
 
39
41
  export const Overlay: React.FC<OverlayProps> = ({
@@ -43,10 +45,15 @@ export const Overlay: React.FC<OverlayProps> = ({
43
45
  onResolved,
44
46
  appName = 'Your App',
45
47
  darkMode = false,
48
+ platforms = [
49
+ { id: 'instagram', name: 'Instagram', icon: require('../assets/images/instagram.png') },
50
+ { id: 'youtube', name: 'YouTube', icon: require('../assets/images/youtube.png') },
51
+ ],
46
52
  }) => {
47
53
  const [selections, setSelections] = useState<{ [key: string]: boolean }>({});
48
54
  const [details, setDetails] = useState<string>('');
49
55
  const [visible, setVisible] = useState(true);
56
+ const [platformToggles, setPlatformToggles] = useState<{[key: string]: boolean}>({});
50
57
  const bottomSheetAnim = useRef(new Animated.Value(0)).current;
51
58
 
52
59
  // Initialize selection state on mount
@@ -57,6 +64,14 @@ export const Overlay: React.FC<OverlayProps> = ({
57
64
  initialSelections[key] = false;
58
65
  });
59
66
  setSelections(initialSelections);
67
+
68
+ // Initialize platform toggles
69
+ const initialToggles: { [key: string]: boolean } = {};
70
+ platforms.forEach((platform) => {
71
+ initialToggles[platform.id] = false;
72
+ });
73
+ setPlatformToggles(initialToggles);
74
+
60
75
  getDetails();
61
76
 
62
77
  // Animate the bottom sheet sliding up
@@ -106,6 +121,13 @@ export const Overlay: React.FC<OverlayProps> = ({
106
121
  });
107
122
  }, [bottomSheetAnim]);
108
123
 
124
+ const togglePlatform = useCallback((platformId: string) => {
125
+ setPlatformToggles(prev => ({
126
+ ...prev,
127
+ [platformId]: !prev[platformId]
128
+ }));
129
+ }, []);
130
+
109
131
  const confirmSelection = useCallback(async () => {
110
132
  try {
111
133
  // Mock app identifier
@@ -119,7 +141,8 @@ export const Overlay: React.FC<OverlayProps> = ({
119
141
  if (__DEV__) {
120
142
  onResolved('https://api2.onairos.uk', 'mock-token', {
121
143
  username,
122
- selections
144
+ selections,
145
+ platforms: platformToggles
123
146
  });
124
147
  closeOverlay();
125
148
  return;
@@ -153,22 +176,24 @@ export const Overlay: React.FC<OverlayProps> = ({
153
176
  confirmations: selections,
154
177
  developerURL: 'devURL',
155
178
  EncryptedUserPin: encryptedModelKey,
156
- account: username,
157
- proofMode: false,
179
+ username: username,
180
+ platforms: platformToggles
158
181
  },
159
182
  });
160
183
 
161
- if (response.data?.apiUrl && response.data?.token) {
162
- onResolved(response.data.apiUrl, response.data.token, {
184
+ if (response && response.data && response.data.APIUrl && response.data.token) {
185
+ onResolved(response.data.APIUrl, response.data.token, {
163
186
  username,
164
- selections
187
+ selections,
188
+ platforms: platformToggles
165
189
  });
166
190
  closeOverlay();
167
191
  } else {
168
192
  // If response doesn't have expected format, use fallbacks
169
193
  onResolved('https://api2.onairos.uk', 'fallback-token', {
170
194
  username,
171
- selections
195
+ selections,
196
+ platforms: platformToggles
172
197
  });
173
198
  closeOverlay();
174
199
  }
@@ -179,6 +204,7 @@ export const Overlay: React.FC<OverlayProps> = ({
179
204
  onResolved('https://api2.onairos.uk', 'error-fallback-token', {
180
205
  username,
181
206
  selections,
207
+ platforms: platformToggles,
182
208
  error: true
183
209
  });
184
210
  closeOverlay();
@@ -186,130 +212,114 @@ export const Overlay: React.FC<OverlayProps> = ({
186
212
  showErrorModal('Failed to confirm selection. Please try again.');
187
213
  }
188
214
  }
189
- }, [selections, username, modelKey, onResolved, closeOverlay]);
215
+ }, [selections, username, modelKey, onResolved, closeOverlay, platformToggles]);
190
216
 
191
217
  const showErrorModal = (errorMessage: string) => {
192
- Alert.alert('Notice', errorMessage, [{ text: 'OK' }]);
218
+ Alert.alert('Error', errorMessage, [{ text: 'OK' }]);
193
219
  };
194
220
 
195
- const selectedCount = Object.values(selections).filter(Boolean).length;
196
-
197
- // Calculate the maximum height of the bottom sheet (80% of screen height)
198
- const maxSheetHeight = SCREEN_HEIGHT * 0.8;
199
-
200
- // Main component rendering
201
221
  return (
202
222
  <Modal
203
223
  visible={visible}
204
- transparent={true}
224
+ transparent
205
225
  animationType="none"
226
+ statusBarTranslucent
206
227
  onRequestClose={closeOverlay}
207
- statusBarTranslucent={true}
208
228
  >
209
- <TouchableOpacity
210
- style={styles.modalOverlay}
229
+ <TouchableOpacity
230
+ style={styles.modalOverlay}
211
231
  activeOpacity={1}
212
232
  onPress={closeOverlay}
213
233
  >
214
- <TouchableWithoutFeedback onPress={e => e.stopPropagation()}>
215
- <Animated.View
234
+ <TouchableWithoutFeedback onPress={(e) => e.stopPropagation()}>
235
+ <Animated.View
216
236
  style={[
217
237
  styles.bottomSheet,
218
238
  darkMode && styles.darkContainer,
219
239
  {
220
- maxHeight: maxSheetHeight,
221
- transform: [{
222
- translateY: bottomSheetAnim.interpolate({
223
- inputRange: [0, 1],
224
- outputRange: [SCREEN_HEIGHT, 0],
225
- })
226
- }]
227
- }
240
+ transform: [
241
+ {
242
+ translateY: bottomSheetAnim.interpolate({
243
+ inputRange: [0, 1],
244
+ outputRange: [SCREEN_HEIGHT, 0],
245
+ }),
246
+ },
247
+ ],
248
+ },
228
249
  ]}
229
250
  >
230
251
  <View style={styles.handleContainer}>
231
252
  <View style={[styles.handle, darkMode && styles.darkHandle]} />
232
253
  </View>
233
-
234
- <View style={[styles.header, darkMode && styles.darkHeader]}>
235
- <View style={styles.headerContent}>
236
- <View style={[styles.appIcon, darkMode && styles.darkAppIcon]}>
237
- <Text style={[styles.appIconText, darkMode && styles.darkText]}>A</Text>
238
- </View>
239
- <Text style={[styles.arrow, darkMode && styles.darkArrow]}>→</Text>
240
- <View style={[styles.onairosIcon, darkMode && styles.darkAppIcon]}>
241
- <Text style={[styles.onairosIconText, darkMode && styles.darkText]}>O</Text>
254
+
255
+ <SafeAreaView style={[styles.container, darkMode && styles.darkContainer]}>
256
+ {/* Header with app icon and arrow to Onairos icon */}
257
+ <View style={[styles.header, darkMode && styles.darkHeader]}>
258
+ <View style={styles.headerContent}>
259
+ <View style={[styles.appIcon, darkMode && styles.darkAppIcon]}>
260
+ <Text style={[styles.appIconText, darkMode && styles.darkText]}>
261
+ {appName.charAt(0)}
262
+ </Text>
263
+ </View>
264
+ <Icon name="arrow_forward" size={24} color={darkMode ? '#999' : '#666'} style={styles.arrow} />
265
+ <View style={[styles.onairosIcon, darkMode && styles.darkOnairosIcon]}>
266
+ <Text style={[styles.onairosIconText, darkMode && styles.darkText]}>O</Text>
267
+ </View>
242
268
  </View>
243
269
  </View>
244
- <Text style={[styles.appName, darkMode && styles.darkSubText]}>{appName}</Text>
245
- </View>
246
270
 
247
- <Text style={[styles.privacyMessage, darkMode && styles.darkSubText]}>
248
- No one will ever see your raw app data
249
- </Text>
271
+ <ScrollView style={styles.content}>
272
+ {/* Main title and description */}
273
+ <View style={styles.titleContainer}>
274
+ <Text style={[styles.mainTitle, darkMode && styles.darkText]}>
275
+ Connect your data to create a Persona of you, to connect to Cosmos
276
+ </Text>
277
+ <Text style={[styles.privacyMessage, darkMode && styles.darkSubText]}>
278
+ None of your app data is shared with ANYONE
279
+ </Text>
280
+ </View>
250
281
 
251
- <ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
252
- {Object.entries(data).map(([key, value]) => (
253
- <View key={key} style={[styles.card, darkMode && styles.darkCard]}>
254
- <TouchableOpacity
255
- style={styles.checkboxContainer}
256
- onPress={() =>
257
- setSelections((prev) => ({
258
- ...prev,
259
- [key]: !prev[key],
260
- }))
261
- }
262
- >
263
- <View
264
- style={[
265
- styles.checkbox,
266
- selections[key] && styles.checkboxSelected,
267
- darkMode && styles.darkCheckbox,
268
- ]}
269
- />
270
- <View style={styles.cardContent}>
271
- <Text style={[styles.cardTitle, darkMode && styles.darkText]}>
272
- {value.type} Insight
273
- </Text>
274
- <Text style={[styles.cardDescription, darkMode && styles.darkSubText]}>
275
- {value.descriptions}
276
- </Text>
277
- {value.reward && (
278
- <Text style={[styles.cardReward, darkMode && styles.darkReward]}>
279
- Reward: {value.reward}
282
+ {/* Platform connection options */}
283
+ <View style={styles.platformsContainer}>
284
+ {platforms.map((platform) => (
285
+ <View key={platform.id} style={[styles.platformItem, darkMode && styles.darkPlatformItem]}>
286
+ <View style={styles.platformInfo}>
287
+ <Image
288
+ source={platform.icon}
289
+ style={styles.platformIcon}
290
+ resizeMode="contain"
291
+ />
292
+ <Text style={[styles.platformName, darkMode && styles.darkText]}>
293
+ {platform.name}
280
294
  </Text>
281
- )}
295
+ </View>
296
+ <Switch
297
+ value={platformToggles[platform.id]}
298
+ onValueChange={() => togglePlatform(platform.id)}
299
+ trackColor={{ false: '#767577', true: '#81b0ff' }}
300
+ thumbColor={platformToggles[platform.id] ? '#2196F3' : '#f4f3f4'}
301
+ />
282
302
  </View>
283
- </TouchableOpacity>
303
+ ))}
284
304
  </View>
285
- ))}
286
- </ScrollView>
305
+ </ScrollView>
287
306
 
288
- <KeyboardAvoidingView
289
- behavior={Platform.OS === 'ios' ? 'padding' : undefined}
290
- >
291
- <SafeAreaView>
292
- <View style={[styles.footer, darkMode && styles.darkFooter]}>
293
- <TouchableOpacity
294
- style={[styles.footerButtonCancel, darkMode && styles.darkFooterButton]}
295
- onPress={closeOverlay}
296
- >
297
- <Text style={[styles.footerButtonText, darkMode && styles.darkSubText]}>Cancel</Text>
298
- </TouchableOpacity>
299
- <Text style={[styles.selectedCount, darkMode && styles.darkSubText]}>
300
- Selected: {selectedCount}
301
- </Text>
302
- <TouchableOpacity
303
- style={[styles.footerButtonConfirm, darkMode && styles.darkFooterButtonConfirm]}
304
- onPress={confirmSelection}
305
- >
306
- <Text style={[styles.footerButtonTextConfirm, darkMode && styles.darkText]}>
307
- Confirm
308
- </Text>
309
- </TouchableOpacity>
310
- </View>
311
- </SafeAreaView>
312
- </KeyboardAvoidingView>
307
+ <View style={[styles.footer, darkMode && styles.darkFooter]}>
308
+ <TouchableOpacity
309
+ style={styles.footerButtonCancel}
310
+ onPress={closeOverlay}
311
+ >
312
+ <Text style={[styles.footerButtonText, darkMode && styles.darkSubText]}>Cancel</Text>
313
+ </TouchableOpacity>
314
+
315
+ <TouchableOpacity
316
+ style={[styles.footerButtonConfirm, darkMode && styles.darkFooterButtonConfirm]}
317
+ onPress={confirmSelection}
318
+ >
319
+ <Text style={[styles.footerButtonTextConfirm, darkMode && { color: '#000' }]}>Connect</Text>
320
+ </TouchableOpacity>
321
+ </View>
322
+ </SafeAreaView>
313
323
  </Animated.View>
314
324
  </TouchableWithoutFeedback>
315
325
  </TouchableOpacity>
@@ -384,12 +394,7 @@ const styles = StyleSheet.create({
384
394
  color: '#fff',
385
395
  },
386
396
  arrow: {
387
- fontSize: 24,
388
397
  marginHorizontal: 16,
389
- color: '#666',
390
- },
391
- darkArrow: {
392
- color: '#999',
393
398
  },
394
399
  onairosIcon: {
395
400
  width: 48,
@@ -399,85 +404,67 @@ const styles = StyleSheet.create({
399
404
  alignItems: 'center',
400
405
  justifyContent: 'center',
401
406
  },
407
+ darkOnairosIcon: {
408
+ backgroundColor: '#2A2A2A',
409
+ },
402
410
  onairosIconText: {
403
411
  fontSize: 24,
404
412
  color: '#000',
405
413
  },
406
- appName: {
407
- fontSize: 16,
408
- color: '#666',
409
- },
410
414
  darkSubText: {
411
415
  color: '#999',
412
416
  },
417
+ titleContainer: {
418
+ marginBottom: 30,
419
+ },
420
+ mainTitle: {
421
+ fontSize: 22,
422
+ fontWeight: '600',
423
+ color: '#000',
424
+ textAlign: 'center',
425
+ marginBottom: 16,
426
+ },
413
427
  privacyMessage: {
414
428
  fontSize: 14,
415
429
  color: '#666',
416
430
  textAlign: 'center',
417
- fontStyle: 'italic',
418
431
  marginBottom: 16,
419
432
  },
420
433
  content: {
421
434
  flex: 1,
422
435
  paddingHorizontal: 24,
423
436
  },
424
- card: {
437
+ platformsContainer: {
438
+ marginTop: 16,
439
+ },
440
+ platformItem: {
441
+ flexDirection: 'row',
442
+ justifyContent: 'space-between',
443
+ alignItems: 'center',
444
+ padding: 16,
425
445
  backgroundColor: '#fff',
426
- borderRadius: 20,
446
+ borderRadius: 16,
427
447
  marginBottom: 16,
428
448
  borderWidth: 1,
429
449
  borderColor: '#eee',
430
- shadowColor: '#000',
431
- shadowOffset: { width: 0, height: 2 },
432
- shadowOpacity: 0.05,
433
- shadowRadius: 8,
434
- elevation: 2,
435
450
  },
436
- darkCard: {
451
+ darkPlatformItem: {
437
452
  backgroundColor: '#2A2A2A',
438
453
  borderColor: '#333',
439
454
  },
440
- checkboxContainer: {
455
+ platformInfo: {
441
456
  flexDirection: 'row',
442
- padding: 16,
443
- alignItems: 'flex-start',
444
- },
445
- checkbox: {
446
- width: 24,
447
- height: 24,
448
- borderRadius: 4,
449
- borderWidth: 2,
450
- borderColor: '#2196F3',
451
- marginRight: 12,
452
- marginTop: 2,
453
- },
454
- darkCheckbox: {
455
- borderColor: '#2196F3',
456
- },
457
- checkboxSelected: {
458
- backgroundColor: '#2196F3',
457
+ alignItems: 'center',
459
458
  },
460
- cardContent: {
461
- flex: 1,
459
+ platformIcon: {
460
+ width: 32,
461
+ height: 32,
462
+ marginRight: 12,
462
463
  },
463
- cardTitle: {
464
+ platformName: {
464
465
  fontSize: 16,
465
- fontWeight: '600',
466
- marginBottom: 4,
467
- color: '#333',
468
- },
469
- cardDescription: {
470
- fontSize: 14,
471
- color: '#666',
472
- marginBottom: 6,
473
- },
474
- cardReward: {
475
- fontSize: 14,
476
- color: '#4CAF50',
477
466
  fontWeight: '500',
478
- },
479
- darkReward: {
480
- color: '#81C784',
467
+ color: '#000',
481
468
  },
482
469
  footer: {
483
470
  flexDirection: 'row',
@@ -520,10 +507,6 @@ const styles = StyleSheet.create({
520
507
  fontSize: 16,
521
508
  fontWeight: '600',
522
509
  },
523
- selectedCount: {
524
- fontSize: 16,
525
- color: '#666',
526
- },
527
510
  lightBackground: {
528
511
  backgroundColor: '#fff',
529
512
  },