@onairos/react-native 1.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.
- package/README.md +334 -0
- package/lib/commonjs/components/DataRequestModal.js +176 -0
- package/lib/commonjs/components/DataRequestModal.js.map +1 -0
- package/lib/commonjs/components/Notification.js +106 -0
- package/lib/commonjs/components/Notification.js.map +1 -0
- package/lib/commonjs/components/OnairosButton.js +575 -0
- package/lib/commonjs/components/OnairosButton.js.map +1 -0
- package/lib/commonjs/components/Overlay.js +818 -0
- package/lib/commonjs/components/Overlay.js.map +1 -0
- package/lib/commonjs/components/UniversalOnboarding.js +173 -0
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -0
- package/lib/commonjs/components/onboarding/OAuthWebView.js +137 -0
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -0
- package/lib/commonjs/components/onboarding/OnboardingHeader.js +74 -0
- package/lib/commonjs/components/onboarding/OnboardingHeader.js.map +1 -0
- package/lib/commonjs/components/onboarding/PinInput.js +283 -0
- package/lib/commonjs/components/onboarding/PinInput.js.map +1 -0
- package/lib/commonjs/components/onboarding/PlatformConnector.js +244 -0
- package/lib/commonjs/components/onboarding/PlatformConnector.js.map +1 -0
- package/lib/commonjs/components/screens/ConnectorScreen.js +145 -0
- package/lib/commonjs/components/screens/ConnectorScreen.js.map +1 -0
- package/lib/commonjs/components/screens/LoadingScreen.js +91 -0
- package/lib/commonjs/components/screens/LoadingScreen.js.map +1 -0
- package/lib/commonjs/components/screens/PinCreationScreen.js +61 -0
- package/lib/commonjs/components/screens/PinCreationScreen.js.map +1 -0
- package/lib/commonjs/constants/index.js +78 -0
- package/lib/commonjs/constants/index.js.map +1 -0
- package/lib/commonjs/hooks/useConnections.js +89 -0
- package/lib/commonjs/hooks/useConnections.js.map +1 -0
- package/lib/commonjs/hooks/useCredentials.js +85 -0
- package/lib/commonjs/hooks/useCredentials.js.map +1 -0
- package/lib/commonjs/index.js +282 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/services/oauthService.js +362 -0
- package/lib/commonjs/services/oauthService.js.map +1 -0
- package/lib/commonjs/types/declarations.d.js +2 -0
- package/lib/commonjs/types/declarations.d.js.map +1 -0
- package/lib/commonjs/types/index.js +2 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/utils/api.js +129 -0
- package/lib/commonjs/utils/api.js.map +1 -0
- package/lib/commonjs/utils/auth.js +111 -0
- package/lib/commonjs/utils/auth.js.map +1 -0
- package/lib/commonjs/utils/crypto.js +62 -0
- package/lib/commonjs/utils/crypto.js.map +1 -0
- package/lib/commonjs/utils/debugHelper.js +64 -0
- package/lib/commonjs/utils/debugHelper.js.map +1 -0
- package/lib/commonjs/utils/onairosApi.js +270 -0
- package/lib/commonjs/utils/onairosApi.js.map +1 -0
- package/lib/commonjs/utils/secureStorage.js +210 -0
- package/lib/commonjs/utils/secureStorage.js.map +1 -0
- package/lib/module/components/DataRequestModal.js +168 -0
- package/lib/module/components/DataRequestModal.js.map +1 -0
- package/lib/module/components/Notification.js +99 -0
- package/lib/module/components/Notification.js.map +1 -0
- package/lib/module/components/OnairosButton.js +550 -0
- package/lib/module/components/OnairosButton.js.map +1 -0
- package/lib/module/components/Overlay.js +825 -0
- package/lib/module/components/Overlay.js.map +1 -0
- package/lib/module/components/UniversalOnboarding.js +164 -0
- package/lib/module/components/UniversalOnboarding.js.map +1 -0
- package/lib/module/components/onboarding/OAuthWebView.js +128 -0
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -0
- package/lib/module/components/onboarding/OnboardingHeader.js +66 -0
- package/lib/module/components/onboarding/OnboardingHeader.js.map +1 -0
- package/lib/module/components/onboarding/PinInput.js +274 -0
- package/lib/module/components/onboarding/PinInput.js.map +1 -0
- package/lib/module/components/onboarding/PlatformConnector.js +235 -0
- package/lib/module/components/onboarding/PlatformConnector.js.map +1 -0
- package/lib/module/components/screens/ConnectorScreen.js +137 -0
- package/lib/module/components/screens/ConnectorScreen.js.map +1 -0
- package/lib/module/components/screens/LoadingScreen.js +83 -0
- package/lib/module/components/screens/LoadingScreen.js.map +1 -0
- package/lib/module/components/screens/PinCreationScreen.js +53 -0
- package/lib/module/components/screens/PinCreationScreen.js.map +1 -0
- package/lib/module/constants/index.js +72 -0
- package/lib/module/constants/index.js.map +1 -0
- package/lib/module/hooks/useConnections.js +81 -0
- package/lib/module/hooks/useConnections.js.map +1 -0
- package/lib/module/hooks/useCredentials.js +77 -0
- package/lib/module/hooks/useCredentials.js.map +1 -0
- package/lib/module/index.js +34 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/services/oauthService.js +352 -0
- package/lib/module/services/oauthService.js.map +1 -0
- package/lib/module/types/declarations.d.js +2 -0
- package/lib/module/types/declarations.d.js.map +1 -0
- package/lib/module/types/index.js +2 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/utils/api.js +117 -0
- package/lib/module/utils/api.js.map +1 -0
- package/lib/module/utils/auth.js +99 -0
- package/lib/module/utils/auth.js.map +1 -0
- package/lib/module/utils/crypto.js +54 -0
- package/lib/module/utils/crypto.js.map +1 -0
- package/lib/module/utils/debugHelper.js +54 -0
- package/lib/module/utils/debugHelper.js.map +1 -0
- package/lib/module/utils/onairosApi.js +256 -0
- package/lib/module/utils/onairosApi.js.map +1 -0
- package/lib/module/utils/secureStorage.js +196 -0
- package/lib/module/utils/secureStorage.js.map +1 -0
- package/package.json +115 -0
- package/src/components/DataRequestModal.tsx +187 -0
- package/src/components/Notification.js +101 -0
- package/src/components/OnairosButton.js +604 -0
- package/src/components/OnairosButton.tsx +182 -0
- package/src/components/Overlay.js +854 -0
- package/src/components/Overlay.tsx +272 -0
- package/src/components/UniversalOnboarding.tsx +184 -0
- package/src/components/onboarding/OAuthWebView.tsx +134 -0
- package/src/components/onboarding/OnboardingHeader.tsx +70 -0
- package/src/components/onboarding/PinInput.tsx +356 -0
- package/src/components/onboarding/PlatformConnector.tsx +297 -0
- package/src/components/screens/ConnectorScreen.tsx +152 -0
- package/src/components/screens/LoadingScreen.tsx +100 -0
- package/src/components/screens/PinCreationScreen.tsx +67 -0
- package/src/constants/index.ts +78 -0
- package/src/hooks/useConnections.ts +90 -0
- package/src/hooks/useCredentials.ts +83 -0
- package/src/index.js +14 -0
- package/src/index.ts +82 -0
- package/src/services/oauthService.ts +360 -0
- package/src/types/declarations.d.ts +26 -0
- package/src/types/index.ts +82 -0
- package/src/utils/api.js +112 -0
- package/src/utils/auth.js +104 -0
- package/src/utils/crypto.js +60 -0
- package/src/utils/debugHelper.ts +53 -0
- package/src/utils/onairosApi.ts +303 -0
- package/src/utils/secureStorage.ts +230 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { View, StyleSheet, SafeAreaView } from 'react-native';
|
|
3
|
+
import { OnboardingHeader } from '../onboarding/OnboardingHeader';
|
|
4
|
+
import { PlatformConnector } from '../onboarding/PlatformConnector';
|
|
5
|
+
import { connectPlatform, disconnectPlatform } from '../../services/oauthService';
|
|
6
|
+
import { getCredentials, updateCredentials } from '../../utils/secureStorage';
|
|
7
|
+
import type { ConnectionStatus } from '../../types';
|
|
8
|
+
|
|
9
|
+
interface ConnectorScreenProps {
|
|
10
|
+
onComplete: () => void;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
AppName: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ConnectorScreen: React.FC<ConnectorScreenProps> = ({
|
|
16
|
+
onComplete,
|
|
17
|
+
onClose,
|
|
18
|
+
AppName,
|
|
19
|
+
}) => {
|
|
20
|
+
const [connections, setConnections] = useState<ConnectionStatus>({});
|
|
21
|
+
const [isConnecting, setIsConnecting] = useState(false);
|
|
22
|
+
|
|
23
|
+
// Load initial connection status
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
loadConnectionStatus();
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
// Load connection status from secure storage
|
|
29
|
+
const loadConnectionStatus = useCallback(async () => {
|
|
30
|
+
try {
|
|
31
|
+
const credentials = await getCredentials();
|
|
32
|
+
|
|
33
|
+
if (credentials?.platforms) {
|
|
34
|
+
const connectionStatus: ConnectionStatus = {};
|
|
35
|
+
|
|
36
|
+
// Transform platforms data to connection status format
|
|
37
|
+
Object.entries(credentials.platforms).forEach(([platform, data]) => {
|
|
38
|
+
if (data && 'username' in data) {
|
|
39
|
+
connectionStatus[platform as keyof ConnectionStatus] = {
|
|
40
|
+
userName: data.username,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
setConnections(connectionStatus);
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('Error loading connection status:', error);
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
// Handle platform connection
|
|
53
|
+
const handleConnect = useCallback(async (platform: string) => {
|
|
54
|
+
try {
|
|
55
|
+
setIsConnecting(true);
|
|
56
|
+
|
|
57
|
+
// Start OAuth flow
|
|
58
|
+
const connectionData = await connectPlatform(platform);
|
|
59
|
+
|
|
60
|
+
// Get current credentials
|
|
61
|
+
const credentials = await getCredentials();
|
|
62
|
+
|
|
63
|
+
if (!credentials) {
|
|
64
|
+
throw new Error('No credentials found');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Update platforms in credentials
|
|
68
|
+
const updatedPlatforms = {
|
|
69
|
+
...credentials.platforms,
|
|
70
|
+
[platform]: {
|
|
71
|
+
token: connectionData.token,
|
|
72
|
+
username: connectionData.username,
|
|
73
|
+
userId: connectionData.userId,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Update stored credentials
|
|
78
|
+
await updateCredentials({
|
|
79
|
+
platforms: updatedPlatforms,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Refresh connection status
|
|
83
|
+
await loadConnectionStatus();
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error(`Error connecting to ${platform}:`, error);
|
|
86
|
+
} finally {
|
|
87
|
+
setIsConnecting(false);
|
|
88
|
+
}
|
|
89
|
+
}, [loadConnectionStatus]);
|
|
90
|
+
|
|
91
|
+
// Handle platform disconnection
|
|
92
|
+
const handleDisconnect = useCallback(async (platform: string) => {
|
|
93
|
+
try {
|
|
94
|
+
setIsConnecting(true);
|
|
95
|
+
|
|
96
|
+
// Get current credentials
|
|
97
|
+
const credentials = await getCredentials();
|
|
98
|
+
|
|
99
|
+
if (!credentials || !credentials.platforms) {
|
|
100
|
+
throw new Error('No credentials or platforms found');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Create updated platforms object without the disconnected platform
|
|
104
|
+
const updatedPlatforms = { ...credentials.platforms };
|
|
105
|
+
delete updatedPlatforms[platform as keyof typeof updatedPlatforms];
|
|
106
|
+
|
|
107
|
+
// Update stored credentials
|
|
108
|
+
await updateCredentials({
|
|
109
|
+
platforms: updatedPlatforms,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Refresh connection status
|
|
113
|
+
await loadConnectionStatus();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(`Error disconnecting from ${platform}:`, error);
|
|
116
|
+
} finally {
|
|
117
|
+
setIsConnecting(false);
|
|
118
|
+
}
|
|
119
|
+
}, [loadConnectionStatus]);
|
|
120
|
+
|
|
121
|
+
// Check if user can proceed to next step
|
|
122
|
+
const canProceed = useCallback(() => {
|
|
123
|
+
const connectedPlatforms = Object.values(connections).filter(Boolean).length;
|
|
124
|
+
return connectedPlatforms >= 2;
|
|
125
|
+
}, [connections]);
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<SafeAreaView style={styles.container}>
|
|
129
|
+
<OnboardingHeader
|
|
130
|
+
title="Connect Your Platforms"
|
|
131
|
+
subtitle={`Connecting to ${AppName}`}
|
|
132
|
+
onClose={onClose}
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
<PlatformConnector
|
|
136
|
+
connections={connections}
|
|
137
|
+
onConnect={handleConnect}
|
|
138
|
+
onDisconnect={handleDisconnect}
|
|
139
|
+
isLoading={isConnecting}
|
|
140
|
+
canProceed={canProceed()}
|
|
141
|
+
onProceed={onComplete}
|
|
142
|
+
/>
|
|
143
|
+
</SafeAreaView>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const styles = StyleSheet.create({
|
|
148
|
+
container: {
|
|
149
|
+
flex: 1,
|
|
150
|
+
backgroundColor: '#fff',
|
|
151
|
+
},
|
|
152
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
ActivityIndicator,
|
|
7
|
+
SafeAreaView,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { COLORS } from '../../constants';
|
|
10
|
+
|
|
11
|
+
interface LoadingScreenProps {
|
|
12
|
+
message: string;
|
|
13
|
+
progress?: number;
|
|
14
|
+
eta?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const LoadingScreen: React.FC<LoadingScreenProps> = ({
|
|
18
|
+
message,
|
|
19
|
+
progress,
|
|
20
|
+
eta,
|
|
21
|
+
}) => {
|
|
22
|
+
// Calculate progress percentage for display
|
|
23
|
+
const progressPercent = progress ? Math.round(progress * 100) : undefined;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<SafeAreaView style={styles.container}>
|
|
27
|
+
<View style={styles.content}>
|
|
28
|
+
<ActivityIndicator size="large" color={COLORS.primary} style={styles.spinner} />
|
|
29
|
+
|
|
30
|
+
<Text style={styles.message}>{message}</Text>
|
|
31
|
+
|
|
32
|
+
{progressPercent !== undefined && (
|
|
33
|
+
<View style={styles.progressContainer}>
|
|
34
|
+
<View style={styles.progressBarBackground}>
|
|
35
|
+
<View
|
|
36
|
+
style={[
|
|
37
|
+
styles.progressBar,
|
|
38
|
+
{ width: `${progressPercent}%` }
|
|
39
|
+
]}
|
|
40
|
+
/>
|
|
41
|
+
</View>
|
|
42
|
+
|
|
43
|
+
<Text style={styles.progressText}>{progressPercent}%</Text>
|
|
44
|
+
</View>
|
|
45
|
+
)}
|
|
46
|
+
|
|
47
|
+
{eta && <Text style={styles.etaText}>{eta}</Text>}
|
|
48
|
+
</View>
|
|
49
|
+
</SafeAreaView>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const styles = StyleSheet.create({
|
|
54
|
+
container: {
|
|
55
|
+
flex: 1,
|
|
56
|
+
backgroundColor: '#fff',
|
|
57
|
+
justifyContent: 'center',
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
},
|
|
60
|
+
content: {
|
|
61
|
+
width: '80%',
|
|
62
|
+
alignItems: 'center',
|
|
63
|
+
padding: 24,
|
|
64
|
+
},
|
|
65
|
+
spinner: {
|
|
66
|
+
marginBottom: 24,
|
|
67
|
+
},
|
|
68
|
+
message: {
|
|
69
|
+
fontSize: 18,
|
|
70
|
+
fontWeight: '600',
|
|
71
|
+
color: '#000',
|
|
72
|
+
textAlign: 'center',
|
|
73
|
+
marginBottom: 24,
|
|
74
|
+
},
|
|
75
|
+
progressContainer: {
|
|
76
|
+
width: '100%',
|
|
77
|
+
marginBottom: 8,
|
|
78
|
+
},
|
|
79
|
+
progressBarBackground: {
|
|
80
|
+
height: 8,
|
|
81
|
+
backgroundColor: '#eee',
|
|
82
|
+
borderRadius: 4,
|
|
83
|
+
overflow: 'hidden',
|
|
84
|
+
marginBottom: 8,
|
|
85
|
+
},
|
|
86
|
+
progressBar: {
|
|
87
|
+
height: '100%',
|
|
88
|
+
backgroundColor: COLORS.primary,
|
|
89
|
+
},
|
|
90
|
+
progressText: {
|
|
91
|
+
fontSize: 14,
|
|
92
|
+
color: '#666',
|
|
93
|
+
textAlign: 'right',
|
|
94
|
+
},
|
|
95
|
+
etaText: {
|
|
96
|
+
fontSize: 14,
|
|
97
|
+
color: '#666',
|
|
98
|
+
marginTop: 8,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { View, StyleSheet, SafeAreaView } from 'react-native';
|
|
3
|
+
import { OnboardingHeader } from '../onboarding/OnboardingHeader';
|
|
4
|
+
import { PinInput } from '../onboarding/PinInput';
|
|
5
|
+
import { updateCredentials, getCredentials } from '../../utils/secureStorage';
|
|
6
|
+
|
|
7
|
+
interface PinCreationScreenProps {
|
|
8
|
+
onComplete: () => void;
|
|
9
|
+
onBack: () => void;
|
|
10
|
+
onClose: () => void;
|
|
11
|
+
AppName: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const PinCreationScreen: React.FC<PinCreationScreenProps> = ({
|
|
15
|
+
onComplete,
|
|
16
|
+
onBack,
|
|
17
|
+
onClose,
|
|
18
|
+
AppName,
|
|
19
|
+
}) => {
|
|
20
|
+
// Handle PIN submission
|
|
21
|
+
const handlePinSubmit = useCallback(async (pin: string) => {
|
|
22
|
+
try {
|
|
23
|
+
// Get current credentials
|
|
24
|
+
const credentials = await getCredentials();
|
|
25
|
+
|
|
26
|
+
if (!credentials) {
|
|
27
|
+
throw new Error('No credentials found');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Update credentials with PIN
|
|
31
|
+
await updateCredentials({
|
|
32
|
+
userPin: pin,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Move to next step
|
|
36
|
+
onComplete();
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('Error saving PIN:', error);
|
|
39
|
+
}
|
|
40
|
+
}, [onComplete]);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<SafeAreaView style={styles.container}>
|
|
44
|
+
<OnboardingHeader
|
|
45
|
+
title="Create a PIN"
|
|
46
|
+
subtitle={`Secure your ${AppName} account`}
|
|
47
|
+
showBackButton
|
|
48
|
+
onBack={onBack}
|
|
49
|
+
onClose={onClose}
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<PinInput
|
|
53
|
+
onSubmit={handlePinSubmit}
|
|
54
|
+
minLength={8}
|
|
55
|
+
requireSpecialChar
|
|
56
|
+
requireNumber
|
|
57
|
+
/>
|
|
58
|
+
</SafeAreaView>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const styles = StyleSheet.create({
|
|
63
|
+
container: {
|
|
64
|
+
flex: 1,
|
|
65
|
+
backgroundColor: '#fff',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { PlatformConfig } from '../types';
|
|
2
|
+
|
|
3
|
+
export const COLORS = {
|
|
4
|
+
primary: '#00BFA5',
|
|
5
|
+
headerBg: '#E0F2F1',
|
|
6
|
+
text: {
|
|
7
|
+
primary: '#000000',
|
|
8
|
+
secondary: '#757575',
|
|
9
|
+
},
|
|
10
|
+
border: '#EEEEEE',
|
|
11
|
+
success: '#4CAF50',
|
|
12
|
+
error: '#F44336',
|
|
13
|
+
instagram: '#E4405F',
|
|
14
|
+
pinterest: '#BD081C',
|
|
15
|
+
reddit: '#FF4500',
|
|
16
|
+
youtube: '#FF0000',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const PLATFORMS: Record<string, PlatformConfig> = {
|
|
20
|
+
instagram: {
|
|
21
|
+
name: 'Instagram',
|
|
22
|
+
icon: 'instagram',
|
|
23
|
+
color: COLORS.instagram,
|
|
24
|
+
description: 'Connect your Instagram account to train your AI model',
|
|
25
|
+
},
|
|
26
|
+
pinterest: {
|
|
27
|
+
name: 'Pinterest',
|
|
28
|
+
icon: 'pinterest',
|
|
29
|
+
color: COLORS.pinterest,
|
|
30
|
+
description: 'Use your Pinterest boards for AI training',
|
|
31
|
+
},
|
|
32
|
+
reddit: {
|
|
33
|
+
name: 'Reddit',
|
|
34
|
+
icon: 'reddit',
|
|
35
|
+
color: COLORS.reddit,
|
|
36
|
+
description: 'Connect Reddit to enhance your AI model',
|
|
37
|
+
},
|
|
38
|
+
youtube: {
|
|
39
|
+
name: 'YouTube',
|
|
40
|
+
icon: 'youtube',
|
|
41
|
+
color: COLORS.youtube,
|
|
42
|
+
description: 'Use YouTube data to improve AI recommendations',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const API_ENDPOINTS = {
|
|
47
|
+
base: 'https://api2.onairos.uk',
|
|
48
|
+
oauth: {
|
|
49
|
+
instagram: '/instagram/auth',
|
|
50
|
+
pinterest: '/pinterest/auth',
|
|
51
|
+
reddit: '/reddit/auth',
|
|
52
|
+
youtube: '/youtube/auth',
|
|
53
|
+
},
|
|
54
|
+
callback: {
|
|
55
|
+
instagram: '/instagram/callback',
|
|
56
|
+
pinterest: '/pinterest/callback',
|
|
57
|
+
reddit: '/reddit/callback',
|
|
58
|
+
youtube: '/youtube/callback',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const STORAGE_KEYS = {
|
|
63
|
+
credentials: 'onairos_credentials',
|
|
64
|
+
connections: 'onairos_connections',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const PIN_REQUIREMENTS = {
|
|
68
|
+
minLength: 8,
|
|
69
|
+
requireUppercase: true,
|
|
70
|
+
requireLowercase: true,
|
|
71
|
+
requireNumber: true,
|
|
72
|
+
requireSpecialChar: true,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const DEEP_LINK_CONFIG = {
|
|
76
|
+
scheme: 'onairosreact',
|
|
77
|
+
host: 'authenticate',
|
|
78
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
import { Linking } from 'react-native';
|
|
3
|
+
import * as Keychain from 'react-native-keychain';
|
|
4
|
+
import { API_ENDPOINTS, STORAGE_KEYS } from '../constants';
|
|
5
|
+
import type { ConnectionStatus } from '../types';
|
|
6
|
+
|
|
7
|
+
export const useConnections = () => {
|
|
8
|
+
const [isConnecting, setIsConnecting] = useState(false);
|
|
9
|
+
|
|
10
|
+
const getConnectionStatus = useCallback(async (): Promise<ConnectionStatus> => {
|
|
11
|
+
try {
|
|
12
|
+
const stored = await Keychain.getGenericPassword(STORAGE_KEYS.connections);
|
|
13
|
+
if (stored) {
|
|
14
|
+
return JSON.parse(stored.password);
|
|
15
|
+
}
|
|
16
|
+
return {};
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('Error getting connection status:', error);
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
const saveConnectionStatus = useCallback(async (status: ConnectionStatus) => {
|
|
24
|
+
try {
|
|
25
|
+
await Keychain.setGenericPassword(
|
|
26
|
+
STORAGE_KEYS.connections,
|
|
27
|
+
JSON.stringify(status)
|
|
28
|
+
);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('Error saving connection status:', error);
|
|
31
|
+
}
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
const connectPlatform = useCallback(async (platform: string) => {
|
|
35
|
+
setIsConnecting(true);
|
|
36
|
+
try {
|
|
37
|
+
// Get OAuth URL from API
|
|
38
|
+
const response = await fetch(
|
|
39
|
+
`${API_ENDPOINTS.base}${API_ENDPOINTS.oauth[platform as keyof typeof API_ENDPOINTS.oauth]}`
|
|
40
|
+
);
|
|
41
|
+
const { url } = await response.json();
|
|
42
|
+
|
|
43
|
+
if (!url) {
|
|
44
|
+
throw new Error('No OAuth URL received');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Open OAuth URL
|
|
48
|
+
await Linking.openURL(url);
|
|
49
|
+
|
|
50
|
+
// Connection status will be updated when the OAuth callback is received
|
|
51
|
+
// This is handled in the UniversalOnboarding component
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(`Error connecting to ${platform}:`, error);
|
|
54
|
+
throw error;
|
|
55
|
+
} finally {
|
|
56
|
+
setIsConnecting(false);
|
|
57
|
+
}
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
const disconnectPlatform = useCallback(async (platform: string) => {
|
|
61
|
+
try {
|
|
62
|
+
const status = await getConnectionStatus();
|
|
63
|
+
delete status[platform as keyof ConnectionStatus];
|
|
64
|
+
await saveConnectionStatus(status);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(`Error disconnecting ${platform}:`, error);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}, [getConnectionStatus, saveConnectionStatus]);
|
|
70
|
+
|
|
71
|
+
const handleOAuthCallback = useCallback(async (platform: string, data: any) => {
|
|
72
|
+
try {
|
|
73
|
+
const status = await getConnectionStatus();
|
|
74
|
+
status[platform as keyof ConnectionStatus] = { userName: data.userName };
|
|
75
|
+
await saveConnectionStatus(status);
|
|
76
|
+
return true;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('Error handling OAuth callback:', error);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}, [getConnectionStatus, saveConnectionStatus]);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
isConnecting,
|
|
85
|
+
connectPlatform,
|
|
86
|
+
disconnectPlatform,
|
|
87
|
+
getConnectionStatus,
|
|
88
|
+
handleOAuthCallback,
|
|
89
|
+
};
|
|
90
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import * as Keychain from 'react-native-keychain';
|
|
3
|
+
import { STORAGE_KEYS } from '../constants';
|
|
4
|
+
import type { CredentialsResult } from '../types';
|
|
5
|
+
|
|
6
|
+
export const useCredentials = () => {
|
|
7
|
+
const hasCredentials = useCallback(async (): Promise<boolean> => {
|
|
8
|
+
try {
|
|
9
|
+
const credentials = await Keychain.getGenericPassword(STORAGE_KEYS.credentials);
|
|
10
|
+
return !!credentials;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error('Error checking credentials:', error);
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}, []);
|
|
16
|
+
|
|
17
|
+
const getCredentials = useCallback(async () => {
|
|
18
|
+
try {
|
|
19
|
+
const credentials = await Keychain.getGenericPassword(STORAGE_KEYS.credentials);
|
|
20
|
+
if (credentials) {
|
|
21
|
+
return JSON.parse(credentials.password);
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error('Error getting credentials:', error);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
const storeCredentials = useCallback(async (
|
|
31
|
+
username: string,
|
|
32
|
+
userPin: string,
|
|
33
|
+
accessToken: string
|
|
34
|
+
): Promise<boolean> => {
|
|
35
|
+
try {
|
|
36
|
+
await Keychain.setGenericPassword(
|
|
37
|
+
STORAGE_KEYS.credentials,
|
|
38
|
+
JSON.stringify({ username, userPin, accessToken })
|
|
39
|
+
);
|
|
40
|
+
return true;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('Error storing credentials:', error);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
const clearCredentials = useCallback(async (): Promise<void> => {
|
|
48
|
+
try {
|
|
49
|
+
await Keychain.resetGenericPassword(STORAGE_KEYS.credentials);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Error clearing credentials:', error);
|
|
52
|
+
}
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
const validateCredentials = useCallback(async (username: string): Promise<CredentialsResult> => {
|
|
56
|
+
try {
|
|
57
|
+
const response = await fetch(`https://api2.onairos.uk/validate`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
},
|
|
62
|
+
body: JSON.stringify({ username }),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const data = await response.json();
|
|
66
|
+
return {
|
|
67
|
+
isValid: data.valid,
|
|
68
|
+
credentials: data.credentials,
|
|
69
|
+
};
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Error validating credentials:', error);
|
|
72
|
+
return { isValid: false };
|
|
73
|
+
}
|
|
74
|
+
}, []);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
hasCredentials,
|
|
78
|
+
getCredentials,
|
|
79
|
+
storeCredentials,
|
|
80
|
+
clearCredentials,
|
|
81
|
+
validateCredentials,
|
|
82
|
+
};
|
|
83
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import OnairosButton from './components/OnairosButton';
|
|
2
|
+
import * as AuthUtils from './utils/auth';
|
|
3
|
+
import * as CryptoUtils from './utils/crypto';
|
|
4
|
+
import * as ApiUtils from './utils/api';
|
|
5
|
+
|
|
6
|
+
// Export the main component
|
|
7
|
+
export default OnairosButton;
|
|
8
|
+
|
|
9
|
+
// Export utilities for advanced usage
|
|
10
|
+
export {
|
|
11
|
+
AuthUtils,
|
|
12
|
+
CryptoUtils,
|
|
13
|
+
ApiUtils
|
|
14
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Components
|
|
2
|
+
export { OnairosButton } from './components/OnairosButton';
|
|
3
|
+
export { UniversalOnboarding } from './components/UniversalOnboarding';
|
|
4
|
+
export { Overlay } from './components/Overlay';
|
|
5
|
+
|
|
6
|
+
// Screen Components
|
|
7
|
+
export { ConnectorScreen } from './components/screens/ConnectorScreen';
|
|
8
|
+
export { PinCreationScreen } from './components/screens/PinCreationScreen';
|
|
9
|
+
export { LoadingScreen } from './components/screens/LoadingScreen';
|
|
10
|
+
|
|
11
|
+
// Onboarding Components
|
|
12
|
+
export { OAuthWebView } from './components/onboarding/OAuthWebView';
|
|
13
|
+
export { PlatformConnector } from './components/onboarding/PlatformConnector';
|
|
14
|
+
export { OnboardingHeader } from './components/onboarding/OnboardingHeader';
|
|
15
|
+
export { PinInput } from './components/onboarding/PinInput';
|
|
16
|
+
|
|
17
|
+
// Hooks
|
|
18
|
+
export { useConnections } from './hooks/useConnections';
|
|
19
|
+
export { useCredentials } from './hooks/useCredentials';
|
|
20
|
+
|
|
21
|
+
// Utilities
|
|
22
|
+
export {
|
|
23
|
+
storeCredentials,
|
|
24
|
+
getCredentials,
|
|
25
|
+
hasCredentials,
|
|
26
|
+
deleteCredentials,
|
|
27
|
+
updateCredentials,
|
|
28
|
+
generateDeviceUsername,
|
|
29
|
+
verifyCredentials,
|
|
30
|
+
} from './utils/secureStorage';
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
validateCredentials,
|
|
34
|
+
createAccount,
|
|
35
|
+
authenticate,
|
|
36
|
+
refreshToken,
|
|
37
|
+
getPlatformData,
|
|
38
|
+
getUserProfile,
|
|
39
|
+
updatePlatformConnections,
|
|
40
|
+
} from './utils/onairosApi';
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
rsaEncrypt,
|
|
44
|
+
sha256,
|
|
45
|
+
base64ToBuffer,
|
|
46
|
+
} from './utils/crypto';
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
logDebug,
|
|
50
|
+
logError,
|
|
51
|
+
isDebugMode,
|
|
52
|
+
} from './utils/debugHelper';
|
|
53
|
+
|
|
54
|
+
// Services
|
|
55
|
+
export {
|
|
56
|
+
connectPlatform,
|
|
57
|
+
disconnectPlatform,
|
|
58
|
+
initializeOAuthService,
|
|
59
|
+
cleanupOAuthService,
|
|
60
|
+
storePlatformConnection,
|
|
61
|
+
} from './services/oauthService';
|
|
62
|
+
|
|
63
|
+
// Types
|
|
64
|
+
export type {
|
|
65
|
+
OnairosButtonProps,
|
|
66
|
+
UniversalOnboardingProps,
|
|
67
|
+
ConnectionStatus,
|
|
68
|
+
PlatformListProps,
|
|
69
|
+
PinInputProps,
|
|
70
|
+
TrainingModalProps,
|
|
71
|
+
OAuthWebViewProps,
|
|
72
|
+
CredentialsResult,
|
|
73
|
+
PlatformConfig,
|
|
74
|
+
ApiResponse,
|
|
75
|
+
} from './types';
|
|
76
|
+
|
|
77
|
+
export type { OnairosCredentials, StorageOptions } from './utils/secureStorage';
|
|
78
|
+
export type { OAuthConfig } from './services/oauthService';
|
|
79
|
+
export type { ApiErrorType, ApiError } from './utils/onairosApi';
|
|
80
|
+
|
|
81
|
+
// Constants
|
|
82
|
+
export { COLORS, PLATFORMS, API_ENDPOINTS, STORAGE_KEYS, PIN_REQUIREMENTS, DEEP_LINK_CONFIG } from './constants';
|