@onairos/react-native 2.0.9 → 3.0.0

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 (37) hide show
  1. package/lib/commonjs/api/index.js +102 -14
  2. package/lib/commonjs/api/index.js.map +1 -1
  3. package/lib/commonjs/components/Onairos.js +89 -0
  4. package/lib/commonjs/components/Onairos.js.map +1 -0
  5. package/lib/commonjs/components/OnairosButton.js +117 -33
  6. package/lib/commonjs/components/OnairosButton.js.map +1 -1
  7. package/lib/commonjs/components/Overlay.js +29 -9
  8. package/lib/commonjs/components/Overlay.js.map +1 -1
  9. package/lib/commonjs/index.js +12 -276
  10. package/lib/commonjs/index.js.map +1 -1
  11. package/lib/commonjs/services/oauthService.js +145 -1
  12. package/lib/commonjs/services/oauthService.js.map +1 -1
  13. package/lib/commonjs/utils/encryption.js +45 -7
  14. package/lib/commonjs/utils/encryption.js.map +1 -1
  15. package/lib/module/api/index.js +103 -14
  16. package/lib/module/api/index.js.map +1 -1
  17. package/lib/module/components/Onairos.js +81 -0
  18. package/lib/module/components/Onairos.js.map +1 -0
  19. package/lib/module/components/OnairosButton.js +120 -35
  20. package/lib/module/components/OnairosButton.js.map +1 -1
  21. package/lib/module/components/Overlay.js +31 -11
  22. package/lib/module/components/Overlay.js.map +1 -1
  23. package/lib/module/index.js +15 -3
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/module/services/oauthService.js +144 -0
  26. package/lib/module/services/oauthService.js.map +1 -1
  27. package/lib/module/utils/encryption.js +43 -6
  28. package/lib/module/utils/encryption.js.map +1 -1
  29. package/package.json +1 -1
  30. package/src/api/index.ts +113 -20
  31. package/src/components/Onairos.tsx +117 -0
  32. package/src/components/OnairosButton.tsx +157 -42
  33. package/src/components/Overlay.tsx +24 -6
  34. package/src/index.ts +19 -5
  35. package/src/services/oauthService.ts +174 -0
  36. package/src/types/index.ts +38 -7
  37. package/src/utils/encryption.ts +45 -6
@@ -1,18 +1,34 @@
1
- import React, { useState } from 'react';
2
- import { TouchableOpacity, Text, StyleSheet, View, ViewStyle, TextStyle } from 'react-native';
1
+ import React, { useState, useCallback } from 'react';
2
+ import {
3
+ TouchableOpacity,
4
+ Text,
5
+ StyleSheet,
6
+ View,
7
+ ViewStyle,
8
+ TextStyle,
9
+ Image,
10
+ ActivityIndicator,
11
+ Alert
12
+ } from 'react-native';
3
13
  import { UniversalOnboarding } from './UniversalOnboarding';
14
+ import { Overlay } from './Overlay';
4
15
  import { COLORS } from '../constants';
5
16
  import type { OnairosButtonProps } from '../types';
17
+ import { hasCredentials, getCredentials, clearCredentials } from '../utils/secureStorage';
18
+ import { onairosApi } from '../api';
6
19
 
20
+ /**
21
+ * OnairosButton Component - A sign-in button similar to Google/Apple sign-in
22
+ */
7
23
  export const OnairosButton: React.FC<OnairosButtonProps> = ({
8
24
  returnLink,
9
25
  prefillUrl,
10
26
  AppName,
11
27
  buttonType = 'normal',
12
28
  requestData,
13
- buttonWidth = 180,
14
- buttonHeight,
15
- hasStroke = false,
29
+ buttonWidth = 240,
30
+ buttonHeight = 48,
31
+ hasStroke = true,
16
32
  enabled = true,
17
33
  buttonForm = 'default',
18
34
  onRejection,
@@ -25,40 +41,100 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
25
41
  testMode = false,
26
42
  }) => {
27
43
  const [showOnboarding, setShowOnboarding] = useState(false);
44
+ const [showOverlay, setShowOverlay] = useState(false);
45
+ const [storedCredentials, setStoredCredentials] = useState<any>(null);
46
+ const [isLoading, setIsLoading] = useState(false);
28
47
 
48
+ const isDarkMode = color === 'black' || (!color && !hasStroke);
49
+
29
50
  const handlePress = async () => {
30
- if (!enabled) return;
51
+ if (!enabled || isLoading) return;
52
+
53
+ setIsLoading(true);
54
+
55
+ try {
56
+ if (preCheck) {
57
+ const shouldProceed = await preCheck();
58
+ if (!shouldProceed) {
59
+ onRejection?.('Precheck validation failed');
60
+ return;
61
+ }
62
+ }
31
63
 
32
- if (preCheck) {
33
- const shouldProceed = await preCheck();
34
- if (!shouldProceed) {
35
- onRejection?.();
36
- return;
64
+ // Check if credentials exist
65
+ const hasStoredCreds = await hasCredentials();
66
+
67
+ if (hasStoredCreds) {
68
+ // If credentials exist, fetch them and verify
69
+ const credentials = await getCredentials();
70
+
71
+ if (!credentials || !credentials.username || !credentials.userPin) {
72
+ // Invalid credentials, clear and start fresh
73
+ await clearCredentials();
74
+ setShowOnboarding(true);
75
+ return;
76
+ }
77
+
78
+ // Validate credentials with server
79
+ const isValid = await onairosApi.validateCredentials(credentials.username);
80
+
81
+ if (!isValid) {
82
+ // Clear invalid credentials
83
+ await clearCredentials();
84
+ setShowOnboarding(true);
85
+ return;
86
+ }
87
+
88
+ // Store and display overlay with valid credentials
89
+ setStoredCredentials(credentials);
90
+ setShowOverlay(true);
91
+ } else {
92
+ // If no credentials, show onboarding
93
+ setShowOnboarding(true);
37
94
  }
95
+ } catch (error) {
96
+ console.error('Error during button press flow:', error);
97
+ Alert.alert('Error', 'An error occurred. Please try again later.');
98
+ onRejection?.(error instanceof Error ? error.message : 'Unknown error');
99
+ } finally {
100
+ setIsLoading(false);
38
101
  }
39
-
40
- setShowOnboarding(true);
41
102
  };
42
103
 
43
- const handleOnboardingComplete = (apiUrl: string, token: string, data: any) => {
104
+ const handleOnboardingComplete = useCallback((apiUrl: string, token: string, data: any) => {
44
105
  setShowOnboarding(false);
45
- onResolved?.(apiUrl, token, data);
46
- };
106
+ if (onResolved) {
107
+ onResolved(apiUrl, token, data);
108
+ }
109
+ }, [onResolved]);
110
+
111
+ const handleOverlayResolved = useCallback((apiUrl: string, token: string, data: any) => {
112
+ setShowOverlay(false);
113
+ if (onResolved) {
114
+ onResolved(apiUrl, token, data);
115
+ }
116
+ }, [onResolved]);
47
117
 
118
+ // Calculate button styles based on props
48
119
  const buttonStyle: ViewStyle[] = [
49
120
  styles.button,
50
121
  buttonType === 'pill' && styles.pillButton,
51
122
  hasStroke && styles.strokedButton,
52
- { width: buttonWidth },
53
- buttonHeight ? { height: buttonHeight } : null,
123
+ {
124
+ width: buttonWidth,
125
+ height: buttonHeight
126
+ },
54
127
  color ? { backgroundColor: color } : null,
128
+ isDarkMode ? styles.darkButton : styles.lightButton,
55
129
  swerv && styles.swervButton,
130
+ !enabled && styles.disabledButton
56
131
  ].filter(Boolean) as ViewStyle[];
57
132
 
133
+ // Calculate text styles based on props
58
134
  const textStyle: TextStyle[] = [
59
135
  styles.buttonText,
60
- hasStroke && styles.strokedButtonText,
61
- color ? styles.customColorText : null,
136
+ isDarkMode ? styles.lightText : styles.darkText,
137
+ !enabled && styles.disabledText
62
138
  ].filter(Boolean) as TextStyle[];
63
139
 
64
140
  return (
@@ -66,37 +142,62 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
66
142
  <TouchableOpacity
67
143
  style={buttonStyle}
68
144
  onPress={handlePress}
69
- disabled={!enabled}
145
+ disabled={!enabled || isLoading}
146
+ accessibilityLabel={`Sign in with Onairos`}
70
147
  >
71
- <Text style={textStyle}>{AppName}</Text>
148
+ {isLoading ? (
149
+ <ActivityIndicator
150
+ size="small"
151
+ color={isDarkMode ? '#fff' : '#000'}
152
+ />
153
+ ) : (
154
+ <>
155
+ {/* Optional Onairos logo could be added here */}
156
+ <Text style={textStyle}>Sign in with Onairos</Text>
157
+ </>
158
+ )}
72
159
  </TouchableOpacity>
73
160
 
74
- <UniversalOnboarding
75
- visible={showOnboarding}
76
- onClose={() => setShowOnboarding(false)}
77
- AppName={AppName}
78
- requestData={requestData}
79
- returnLink={returnLink}
80
- onComplete={handleOnboardingComplete}
81
- preferredPlatform={preferredPlatform}
82
- debug={debug}
83
- test={testMode}
84
- />
161
+ {showOnboarding && (
162
+ <UniversalOnboarding
163
+ visible={showOnboarding}
164
+ onClose={() => {
165
+ setShowOnboarding(false);
166
+ onRejection?.('User closed onboarding');
167
+ }}
168
+ AppName={AppName}
169
+ requestData={requestData}
170
+ returnLink={returnLink}
171
+ onComplete={handleOnboardingComplete}
172
+ preferredPlatform={preferredPlatform}
173
+ debug={debug}
174
+ test={testMode}
175
+ />
176
+ )}
177
+
178
+ {showOverlay && storedCredentials && (
179
+ <Overlay
180
+ data={requestData || {}}
181
+ username={storedCredentials.username}
182
+ modelKey={storedCredentials.userPin || ''}
183
+ onResolved={handleOverlayResolved}
184
+ />
185
+ )}
85
186
  </View>
86
187
  );
87
188
  };
88
189
 
89
190
  const styles = StyleSheet.create({
90
191
  button: {
91
- backgroundColor: '#000',
92
- paddingVertical: 12,
93
- paddingHorizontal: 24,
94
- borderRadius: 8,
192
+ flexDirection: 'row',
95
193
  alignItems: 'center',
96
194
  justifyContent: 'center',
195
+ paddingVertical: 12,
196
+ paddingHorizontal: 16,
197
+ borderRadius: 4,
97
198
  },
98
199
  pillButton: {
99
- borderRadius: 20,
200
+ borderRadius: 24,
100
201
  },
101
202
  strokedButton: {
102
203
  backgroundColor: 'transparent',
@@ -106,15 +207,29 @@ const styles = StyleSheet.create({
106
207
  swervButton: {
107
208
  transform: [{ rotate: '-2deg' }],
108
209
  },
210
+ darkButton: {
211
+ backgroundColor: '#000',
212
+ borderColor: '#000',
213
+ },
214
+ lightButton: {
215
+ backgroundColor: '#fff',
216
+ borderColor: '#000',
217
+ },
218
+ disabledButton: {
219
+ opacity: 0.6,
220
+ },
109
221
  buttonText: {
110
- color: '#fff',
111
222
  fontSize: 16,
112
223
  fontWeight: '600',
224
+ textAlign: 'center',
225
+ },
226
+ lightText: {
227
+ color: '#fff',
113
228
  },
114
- strokedButtonText: {
229
+ darkText: {
115
230
  color: '#000',
116
231
  },
117
- customColorText: {
118
- color: '#fff',
232
+ disabledText: {
233
+ opacity: 0.7,
119
234
  },
120
235
  });
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState, useEffect, useRef } from 'react';
2
2
  import {
3
3
  View,
4
4
  Text,
@@ -7,6 +7,7 @@ import {
7
7
  ScrollView,
8
8
  Alert,
9
9
  Platform,
10
+ Dimensions,
10
11
  } from 'react-native';
11
12
  import { BottomSheetModal, BottomSheetBackdrop } from '@gorhom/bottom-sheet';
12
13
  // import DeviceInfo from 'react-native-device-info'; // Comment out device info import
@@ -35,7 +36,8 @@ export const Overlay: React.FC<OverlayProps> = ({
35
36
  }) => {
36
37
  const [selections, setSelections] = useState<{ [key: string]: boolean }>({});
37
38
  const [details, setDetails] = useState<string>('');
38
- const bottomSheetRef = React.useRef<BottomSheetModal>(null);
39
+ const bottomSheetRef = useRef<BottomSheetModal>(null);
40
+ const snapPoints = ['60%']; // Set to 60% of screen height
39
41
 
40
42
  useEffect(() => {
41
43
  // Initialize selection state
@@ -45,6 +47,11 @@ export const Overlay: React.FC<OverlayProps> = ({
45
47
  });
46
48
  setSelections(initialSelections);
47
49
  getDetails();
50
+
51
+ // Present the bottom sheet when component mounts
52
+ setTimeout(() => {
53
+ bottomSheetRef.current?.present();
54
+ }, 100);
48
55
  }, []);
49
56
 
50
57
  const getDetails = async () => {
@@ -107,14 +114,19 @@ export const Overlay: React.FC<OverlayProps> = ({
107
114
  return (
108
115
  <BottomSheetModal
109
116
  ref={bottomSheetRef}
110
- snapPoints={['80%']}
117
+ snapPoints={snapPoints}
118
+ handleIndicatorStyle={styles.handleIndicator}
111
119
  backdropComponent={(props) => (
112
120
  <BottomSheetBackdrop
113
121
  {...props}
114
122
  appearsOnIndex={0}
115
123
  disappearsOnIndex={-1}
124
+ opacity={0.7}
116
125
  />
117
126
  )}
127
+ enablePanDownToClose={true}
128
+ keyboardBehavior="interactive"
129
+ keyboardBlurBehavior="restore"
118
130
  >
119
131
  <View style={styles.container}>
120
132
  <View style={styles.header}>
@@ -179,12 +191,18 @@ export const Overlay: React.FC<OverlayProps> = ({
179
191
  );
180
192
  };
181
193
 
194
+ const { width: SCREEN_WIDTH } = Dimensions.get('window');
195
+
182
196
  const styles = StyleSheet.create({
183
197
  container: {
184
198
  flex: 1,
185
199
  backgroundColor: COLORS.white,
186
- borderTopLeftRadius: 10,
187
- borderTopRightRadius: 10,
200
+ width: SCREEN_WIDTH,
201
+ },
202
+ handleIndicator: {
203
+ backgroundColor: '#999',
204
+ width: 40,
205
+ height: 5,
188
206
  },
189
207
  header: {
190
208
  flexDirection: 'row',
@@ -207,7 +225,7 @@ const styles = StyleSheet.create({
207
225
  },
208
226
  username: {
209
227
  fontSize: 18,
210
- color: COLORS.primary,
228
+ color: COLORS.white,
211
229
  },
212
230
  content: {
213
231
  flex: 1,
package/src/index.ts CHANGED
@@ -1,7 +1,13 @@
1
- // Components
1
+ /**
2
+ * Onairos React Native SDK
3
+ * A React Native implementation for Onairos personalized data integration
4
+ */
5
+
6
+ // Main components
7
+ export { Onairos } from './components/Onairos';
2
8
  export { OnairosButton } from './components/OnairosButton';
9
+ export { Overlay as OnairosOverlay } from './components/Overlay';
3
10
  export { UniversalOnboarding } from './components/UniversalOnboarding';
4
- export { Overlay } from './components/Overlay';
5
11
 
6
12
  // Screen Components
7
13
  export { ConnectorScreen } from './components/screens/ConnectorScreen';
@@ -15,8 +21,8 @@ export { OnboardingHeader } from './components/onboarding/OnboardingHeader';
15
21
  export { PinInput } from './components/onboarding/PinInput';
16
22
 
17
23
  // Hooks
18
- export { useConnections } from './hooks/useConnections';
19
24
  export { useCredentials } from './hooks/useCredentials';
25
+ export { useConnections } from './hooks/useConnections';
20
26
 
21
27
  // Utilities
22
28
  export {
@@ -63,8 +69,10 @@ export {
63
69
  // Types
64
70
  export type {
65
71
  OnairosButtonProps,
72
+ DataTier,
66
73
  UniversalOnboardingProps,
67
74
  ConnectionStatus,
75
+ OnairosCredentials,
68
76
  PlatformListProps,
69
77
  PinInputProps,
70
78
  TrainingModalProps,
@@ -74,9 +82,15 @@ export type {
74
82
  ApiResponse,
75
83
  } from './types';
76
84
 
77
- export type { OnairosCredentials, StorageOptions } from './utils/secureStorage';
85
+ export type { StorageOptions } from './utils/secureStorage';
78
86
  export type { OAuthConfig } from './services/oauthService';
79
87
  export type { ApiErrorType, ApiError } from './utils/onairosApi';
80
88
 
81
89
  // Constants
82
- export { COLORS, PLATFORMS, API_ENDPOINTS, STORAGE_KEYS, PIN_REQUIREMENTS, DEEP_LINK_CONFIG } from './constants';
90
+ export { COLORS, PLATFORMS, API_ENDPOINTS, STORAGE_KEYS, PIN_REQUIREMENTS, DEEP_LINK_CONFIG } from './constants';
91
+
92
+ // API and Services
93
+ export { onairosApi } from './api';
94
+ export { OAuthService } from './services/OAuthService';
95
+ export * from './utils/secureStorage';
96
+ export * from './utils/encryption';
@@ -1,6 +1,7 @@
1
1
  import { Linking, Platform } from 'react-native';
2
2
  import { updateCredentials, OnairosCredentials } from '../utils/secureStorage';
3
3
  import { sha256 } from '../utils/crypto';
4
+ import { onairosApi } from '../api';
4
5
 
5
6
  // Define OAuth configuration types
6
7
  export interface OAuthConfig {
@@ -358,3 +359,176 @@ export const storePlatformConnection = async (
358
359
  return false;
359
360
  }
360
361
  };
362
+
363
+ export interface AuthorizationData {
364
+ accountName: string;
365
+ authUrl: string;
366
+ }
367
+
368
+ export interface PlatformConnectionResult {
369
+ success: boolean;
370
+ userName?: string;
371
+ error?: string;
372
+ }
373
+
374
+ /**
375
+ * Service for handling OAuth connections to various platforms
376
+ */
377
+ export const OAuthService = {
378
+ // Base API URL
379
+ _apiBaseUrl: 'https://api2.onairos.uk',
380
+
381
+ /**
382
+ * Connect to a specific platform using OAuth
383
+ * @param platform The platform to connect to (e.g., 'instagram', 'youtube')
384
+ * @returns A promise that resolves to a connection result
385
+ */
386
+ connectPlatform: async (platform: string): Promise<PlatformConnectionResult> => {
387
+ try {
388
+ console.log(`[OAuth] Initiating connection to ${platform}`);
389
+
390
+ // Get authorization data from API
391
+ const authData = await OAuthService._getAuthorizationData(platform);
392
+
393
+ if (!authData || !authData.accountName) {
394
+ throw new Error(`Failed to get authorization data for ${platform}`);
395
+ }
396
+
397
+ // Launch the OAuth flow in a WebView
398
+ const success = await OAuthService._launchOAuthFlow(
399
+ platform,
400
+ `${OAuthService._apiBaseUrl}/${authData.accountName}/authorize`,
401
+ `onairos://${platform.toLowerCase()}/callback`
402
+ );
403
+
404
+ return {
405
+ success,
406
+ userName: success ? `User_${platform}` : undefined,
407
+ error: success ? undefined : `Failed to connect to ${platform}`
408
+ };
409
+ } catch (error) {
410
+ console.error(`${platform} connection error:`, error);
411
+ return {
412
+ success: false,
413
+ error: error instanceof Error ? error.message : 'Unknown error'
414
+ };
415
+ }
416
+ },
417
+
418
+ /**
419
+ * Get authorization data for a platform from the API
420
+ * @param platform The platform to get authorization data for
421
+ * @returns Authorization data for the platform
422
+ */
423
+ _getAuthorizationData: async (platform: string): Promise<AuthorizationData> => {
424
+ try {
425
+ // For testing, we can use a mock app ID
426
+ let appId = 'com.onairos.mock';
427
+
428
+ // In real implementation, we would get this from the app's package info
429
+ try {
430
+ // This would normally use react-native-device-info or similar
431
+ // appId = await DeviceInfo.getBundleId();
432
+ } catch (e) {
433
+ console.warn('Failed to get app identifier:', e);
434
+ }
435
+
436
+ const response = await onairosApi.post('getOAuthData', {
437
+ platform,
438
+ appId: appId,
439
+ redirectUri: `onairos://${platform.toLowerCase()}/callback`,
440
+ });
441
+
442
+ if (response && response.accountName) {
443
+ return {
444
+ accountName: response.accountName,
445
+ authUrl: `${OAuthService._apiBaseUrl}/${response.accountName}/authorize`,
446
+ };
447
+ } else {
448
+ throw new Error('Invalid response from getOAuthData');
449
+ }
450
+ } catch (error) {
451
+ console.error('Error getting authorization data:', error);
452
+ throw error;
453
+ }
454
+ },
455
+
456
+ /**
457
+ * Launch the OAuth flow for a platform
458
+ * @param platform The platform to launch the OAuth flow for
459
+ * @param authUrl The URL to authorize with
460
+ * @param callbackUrlPattern The URL pattern to expect as a callback
461
+ * @returns A promise that resolves to true if the connection was successful
462
+ */
463
+ _launchOAuthFlow: async (
464
+ platform: string,
465
+ authUrl: string,
466
+ callbackUrlPattern: string
467
+ ): Promise<boolean> => {
468
+ try {
469
+ console.log(`[OAuth] Opening URL for ${platform}: ${authUrl}`);
470
+
471
+ // For now, we'll use a simpler approach just to mock the flow
472
+ // In a real implementation, this would open a WebView in a modal
473
+ // and handle the OAuth callback
474
+
475
+ // Check if we can open the URL
476
+ const canOpen = await Linking.canOpenURL(authUrl);
477
+
478
+ if (!canOpen) {
479
+ throw new Error(`Cannot open URL: ${authUrl}`);
480
+ }
481
+
482
+ // We'll simulate a successful connection after a delay
483
+ // In a real app, this would be handled by the WebView navigation
484
+ await new Promise(resolve => setTimeout(resolve, 1000));
485
+
486
+ // Return success
487
+ return true;
488
+ } catch (error) {
489
+ console.error(`Error launching OAuth flow for ${platform}:`, error);
490
+ return false;
491
+ }
492
+ },
493
+
494
+ /**
495
+ * Handle an OAuth callback URL
496
+ * @param url The callback URL to handle
497
+ * @returns The result of processing the callback
498
+ */
499
+ handleCallback: async (url: string): Promise<PlatformConnectionResult> => {
500
+ try {
501
+ console.log(`[OAuth] Handling callback URL: ${url}`);
502
+
503
+ // Extract the platform and parameters from the URL
504
+ const urlParts = url.split('/');
505
+ const platform = urlParts[2]; // Assuming format is onairos://platform/callback
506
+
507
+ // Extract query parameters
508
+ const params = new URLSearchParams(url.split('?')[1] || '');
509
+ const code = params.get('code');
510
+
511
+ if (!code) {
512
+ return {
513
+ success: false,
514
+ error: 'No authorization code found in callback URL'
515
+ };
516
+ }
517
+
518
+ // In a real implementation, we would send the code to the API
519
+ // to get an access token
520
+
521
+ // Simulate a successful connection
522
+ return {
523
+ success: true,
524
+ userName: `User_${platform}`
525
+ };
526
+ } catch (error) {
527
+ console.error('Error handling OAuth callback:', error);
528
+ return {
529
+ success: false,
530
+ error: error instanceof Error ? error.message : 'Unknown error'
531
+ };
532
+ }
533
+ }
534
+ };
@@ -19,7 +19,7 @@ export interface OnairosButtonProps {
19
19
  hasStroke?: boolean;
20
20
  enabled?: boolean;
21
21
  buttonForm?: 'default' | 'login' | 'signup';
22
- onRejection?: () => void;
22
+ onRejection?: (error?: string) => void;
23
23
  onResolved?: (apiUrl: string, token: string, userData: any) => void;
24
24
  preCheck?: () => Promise<boolean>;
25
25
  color?: string;
@@ -81,13 +81,31 @@ export interface OAuthWebViewProps {
81
81
  onClose: () => void;
82
82
  }
83
83
 
84
- export interface CredentialsResult {
85
- isValid: boolean;
86
- credentials?: {
87
- username?: string;
88
- userPin?: string;
89
- accessToken?: string;
84
+ export interface OnairosCredentials {
85
+ username: string;
86
+ accessToken?: string;
87
+ refreshToken?: string;
88
+ userPin?: string;
89
+ platforms?: {
90
+ instagram?: { token: string; username: string };
91
+ youtube?: { token: string; username: string };
92
+ pinterest?: { token: string; username: string };
93
+ reddit?: { token: string; username: string };
90
94
  };
95
+ createdAt: number;
96
+ }
97
+
98
+ export interface OverlayProps {
99
+ data: {
100
+ [key: string]: {
101
+ type: string;
102
+ descriptions: string;
103
+ reward: string;
104
+ };
105
+ };
106
+ username: string;
107
+ modelKey: string;
108
+ onResolved: (apiUrl: string, accessToken: string, loginDetails: any) => void;
91
109
  }
92
110
 
93
111
  export interface PlatformConfig {
@@ -97,6 +115,19 @@ export interface PlatformConfig {
97
115
  description?: string;
98
116
  }
99
117
 
118
+ export interface BiometricOptions {
119
+ title: string;
120
+ subtitle?: string;
121
+ description?: string;
122
+ cancelText?: string;
123
+ }
124
+
125
+ export interface PinRequirements {
126
+ minLength: number;
127
+ requireSpecialChar: boolean;
128
+ requireNumber: boolean;
129
+ }
130
+
100
131
  export interface ApiResponse<T> {
101
132
  success: boolean;
102
133
  data?: T;