@onairos/react-native 1.0.2 → 2.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/lib/commonjs/api/index.js +34 -0
- package/lib/commonjs/api/index.js.map +1 -0
- package/lib/commonjs/components/OnairosButton.js +69 -122
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/Overlay.js +173 -197
- package/lib/commonjs/components/Overlay.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +8 -5
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/constants/index.js +13 -9
- package/lib/commonjs/constants/index.js.map +1 -1
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/encryption.js +32 -0
- package/lib/commonjs/utils/encryption.js.map +1 -0
- package/lib/module/api/index.js +27 -0
- package/lib/module/api/index.js.map +1 -0
- package/lib/module/components/OnairosButton.js +71 -123
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/Overlay.js +175 -198
- package/lib/module/components/Overlay.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +8 -5
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/constants/index.js +13 -9
- package/lib/module/constants/index.js.map +1 -1
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/encryption.js +24 -0
- package/lib/module/utils/encryption.js.map +1 -0
- package/package.json +1 -1
- package/src/api/index.ts +33 -0
- package/src/components/OnairosButton.tsx +74 -131
- package/src/components/Overlay.tsx +190 -185
- package/src/components/UniversalOnboarding.tsx +7 -4
- package/src/constants/index.ts +12 -8
- package/src/types/index.ts +34 -16
- package/src/types.ts +29 -0
- package/src/utils/encryption.ts +25 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RSA } from 'react-native-rsa-native';
|
|
2
|
+
import { onairosApi } from '../api';
|
|
3
|
+
export const encryptModelKey = async (publicKey, modelKey) => {
|
|
4
|
+
try {
|
|
5
|
+
const encrypted = await RSA.encrypt(modelKey, publicKey);
|
|
6
|
+
return encrypted;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
console.error('Error encrypting model key:', error);
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const getServerPublicKey = async () => {
|
|
13
|
+
try {
|
|
14
|
+
const response = await onairosApi.get('public/getPublicKey');
|
|
15
|
+
if (response && response.publicKey) {
|
|
16
|
+
return response.publicKey;
|
|
17
|
+
}
|
|
18
|
+
throw new Error('Server response does not contain publicKey field');
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('Error getting server public key:', error);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["RSA","onairosApi","encryptModelKey","publicKey","modelKey","encrypted","encrypt","error","console","getServerPublicKey","response","get","Error"],"sourceRoot":"..\\..\\..\\src","sources":["utils/encryption.ts"],"mappings":"AAAA,SAASA,GAAG,QAAQ,yBAAyB;AAC7C,SAASC,UAAU,QAAQ,QAAQ;AAEnC,OAAO,MAAMC,eAAe,GAAG,MAAAA,CAAOC,SAAiB,EAAEC,QAAgB,KAAsB;EAC7F,IAAI;IACF,MAAMC,SAAS,GAAG,MAAML,GAAG,CAACM,OAAO,CAACF,QAAQ,EAAED,SAAS,CAAC;IACxD,OAAOE,SAAS;EAClB,CAAC,CAAC,OAAOE,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,6BAA6B,EAAEA,KAAK,CAAC;IACnD,MAAMA,KAAK;EACb;AACF,CAAC;AAED,OAAO,MAAME,kBAAkB,GAAG,MAAAA,CAAA,KAA6B;EAC7D,IAAI;IACF,MAAMC,QAAQ,GAAG,MAAMT,UAAU,CAACU,GAAG,CAAC,qBAAqB,CAAC;IAC5D,IAAID,QAAQ,IAAIA,QAAQ,CAACP,SAAS,EAAE;MAClC,OAAOO,QAAQ,CAACP,SAAS;IAC3B;IACA,MAAM,IAAIS,KAAK,CAAC,kDAAkD,CAAC;EACrE,CAAC,CAAC,OAAOL,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,kCAAkC,EAAEA,KAAK,CAAC;IACxD,MAAMA,KAAK;EACb;AACF,CAAC","ignoreList":[]}
|
package/package.json
CHANGED
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
|
|
3
|
+
const BASE_URL = 'https://api2.onairos.uk';
|
|
4
|
+
|
|
5
|
+
class OnairosApi {
|
|
6
|
+
private baseUrl: string;
|
|
7
|
+
|
|
8
|
+
constructor(baseUrl: string = BASE_URL) {
|
|
9
|
+
this.baseUrl = baseUrl;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async get(endpoint: string) {
|
|
13
|
+
try {
|
|
14
|
+
const response = await axios.get(`${this.baseUrl}/${endpoint}`);
|
|
15
|
+
return response.data;
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('API GET Error:', error);
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async post(endpoint: string, data: any) {
|
|
23
|
+
try {
|
|
24
|
+
const response = await axios.post(`${this.baseUrl}/${endpoint}`, data);
|
|
25
|
+
return response.data;
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('API POST Error:', error);
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const onairosApi = new OnairosApi();
|
|
@@ -1,132 +1,79 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
TouchableOpacity,
|
|
4
|
-
StyleSheet,
|
|
5
|
-
View,
|
|
6
|
-
Text,
|
|
7
|
-
Platform,
|
|
8
|
-
Linking,
|
|
9
|
-
Modal,
|
|
10
|
-
} from 'react-native';
|
|
11
|
-
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
12
|
-
import * as Keychain from 'react-native-keychain';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { TouchableOpacity, Text, StyleSheet, View, Dimensions } from 'react-native';
|
|
13
3
|
import { UniversalOnboarding } from './UniversalOnboarding';
|
|
14
|
-
import {
|
|
15
|
-
import { useCredentials } from '../hooks/useCredentials';
|
|
16
|
-
// import { validateCredentials } from '../utils/auth';
|
|
17
|
-
// import { COLORS } from '../constants';
|
|
4
|
+
import { COLORS } from '../constants';
|
|
18
5
|
import type { OnairosButtonProps } from '../types';
|
|
19
6
|
|
|
20
7
|
export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
8
|
+
returnLink,
|
|
9
|
+
prefillUrl,
|
|
21
10
|
AppName,
|
|
11
|
+
buttonType = 'normal',
|
|
22
12
|
requestData,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
buttonWidth = 180,
|
|
14
|
+
buttonHeight,
|
|
15
|
+
hasStroke = false,
|
|
16
|
+
enabled = true,
|
|
17
|
+
buttonForm = 'default',
|
|
18
|
+
onRejection,
|
|
27
19
|
onResolved,
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
preCheck,
|
|
21
|
+
color,
|
|
22
|
+
swerv = false,
|
|
30
23
|
debug = false,
|
|
31
|
-
|
|
24
|
+
preferredPlatform,
|
|
25
|
+
testMode = false,
|
|
32
26
|
}) => {
|
|
33
27
|
const [showOnboarding, setShowOnboarding] = useState(false);
|
|
34
|
-
const [showDataRequest, setShowDataRequest] = useState(false);
|
|
35
|
-
const { hasCredentials, getCredentials, validateCredentials } = useCredentials();
|
|
36
|
-
const [loading, setLoading] = useState(false);
|
|
37
28
|
|
|
38
|
-
const handlePress =
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const hasExisting = await hasCredentials();
|
|
42
|
-
|
|
43
|
-
if (!hasExisting) {
|
|
44
|
-
setShowOnboarding(true);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const credentials = await getCredentials();
|
|
49
|
-
if (!credentials) {
|
|
50
|
-
setShowOnboarding(true);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
29
|
+
const handlePress = async () => {
|
|
30
|
+
if (!enabled) return;
|
|
53
31
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
32
|
+
if (preCheck) {
|
|
33
|
+
const shouldProceed = await preCheck();
|
|
34
|
+
if (!shouldProceed) {
|
|
35
|
+
onRejection?.();
|
|
57
36
|
return;
|
|
58
37
|
}
|
|
59
|
-
|
|
60
|
-
// If we have valid credentials, show data request modal
|
|
61
|
-
setShowDataRequest(true);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.error('Error in button press:', error);
|
|
64
|
-
setShowOnboarding(true);
|
|
65
|
-
} finally {
|
|
66
|
-
setLoading(false);
|
|
67
38
|
}
|
|
68
|
-
}, [hasCredentials, getCredentials, validateCredentials]);
|
|
69
39
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
'https://api2.onairos.uk',
|
|
76
|
-
credentials.accessToken,
|
|
77
|
-
credentials
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
setShowDataRequest(false);
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error('Error handling data request accept:', error);
|
|
40
|
+
if (buttonForm === 'signup') {
|
|
41
|
+
setShowOnboarding(true);
|
|
42
|
+
} else {
|
|
43
|
+
// Handle login flow
|
|
44
|
+
// TODO: Implement login flow according to account.md
|
|
83
45
|
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
// Setup deep linking
|
|
88
|
-
const handleDeepLink = ({ url }: { url: string }) => {
|
|
89
|
-
if (url.includes('onairosreact://authenticate')) {
|
|
90
|
-
// Handle authentication callback
|
|
91
|
-
const params = new URL(url).searchParams;
|
|
92
|
-
const nonce = params.get('nonce');
|
|
93
|
-
const callback = params.get('callback');
|
|
94
|
-
|
|
95
|
-
if (nonce && callback) {
|
|
96
|
-
// Process authentication
|
|
97
|
-
setShowOnboarding(false);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
Linking.addEventListener('url', handleDeepLink);
|
|
46
|
+
};
|
|
103
47
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// Linking.removeEventListener('url', handleDeepLink);
|
|
109
|
-
// }
|
|
110
|
-
};
|
|
111
|
-
}, []);
|
|
48
|
+
const handleOnboardingComplete = (apiUrl: string, token: string, data: any) => {
|
|
49
|
+
setShowOnboarding(false);
|
|
50
|
+
onResolved?.(apiUrl, token, data);
|
|
51
|
+
};
|
|
112
52
|
|
|
113
|
-
const
|
|
53
|
+
const buttonStyle = [
|
|
114
54
|
styles.button,
|
|
115
|
-
buttonType === 'pill'
|
|
116
|
-
|
|
55
|
+
buttonType === 'pill' && styles.pillButton,
|
|
56
|
+
hasStroke && styles.strokedButton,
|
|
57
|
+
{ width: buttonWidth },
|
|
58
|
+
buttonHeight && { height: buttonHeight },
|
|
59
|
+
color && { backgroundColor: color },
|
|
60
|
+
swerv && styles.swervButton,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const textStyle = [
|
|
64
|
+
styles.buttonText,
|
|
65
|
+
hasStroke && styles.strokedButtonText,
|
|
66
|
+
color && styles.customColorText,
|
|
117
67
|
];
|
|
118
68
|
|
|
119
69
|
return (
|
|
120
|
-
|
|
70
|
+
<View>
|
|
121
71
|
<TouchableOpacity
|
|
122
|
-
style={
|
|
72
|
+
style={buttonStyle}
|
|
123
73
|
onPress={handlePress}
|
|
124
|
-
disabled={
|
|
74
|
+
disabled={!enabled}
|
|
125
75
|
>
|
|
126
|
-
<
|
|
127
|
-
{buttonType === 'pill' && (
|
|
128
|
-
<Text style={styles.buttonText}>Connect with Onairos</Text>
|
|
129
|
-
)}
|
|
76
|
+
<Text style={textStyle}>{AppName}</Text>
|
|
130
77
|
</TouchableOpacity>
|
|
131
78
|
|
|
132
79
|
<UniversalOnboarding
|
|
@@ -135,48 +82,44 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
135
82
|
AppName={AppName}
|
|
136
83
|
requestData={requestData}
|
|
137
84
|
returnLink={returnLink}
|
|
138
|
-
onComplete={
|
|
139
|
-
|
|
85
|
+
onComplete={handleOnboardingComplete}
|
|
86
|
+
preferredPlatform={preferredPlatform}
|
|
140
87
|
debug={debug}
|
|
141
|
-
test={
|
|
88
|
+
test={testMode}
|
|
142
89
|
/>
|
|
143
|
-
|
|
144
|
-
<DataRequestModal
|
|
145
|
-
visible={showDataRequest}
|
|
146
|
-
onClose={() => setShowDataRequest(false)}
|
|
147
|
-
onAccept={handleDataRequestAccept}
|
|
148
|
-
requestData={requestData}
|
|
149
|
-
AppName={AppName}
|
|
150
|
-
/>
|
|
151
|
-
</>
|
|
90
|
+
</View>
|
|
152
91
|
);
|
|
153
92
|
};
|
|
154
93
|
|
|
155
94
|
const styles = StyleSheet.create({
|
|
156
95
|
button: {
|
|
96
|
+
backgroundColor: '#000',
|
|
97
|
+
paddingVertical: 12,
|
|
98
|
+
paddingHorizontal: 24,
|
|
99
|
+
borderRadius: 8,
|
|
157
100
|
alignItems: 'center',
|
|
158
101
|
justifyContent: 'center',
|
|
159
|
-
elevation: 3,
|
|
160
|
-
shadowColor: '#000',
|
|
161
|
-
shadowOffset: { width: 0, height: 2 },
|
|
162
|
-
shadowOpacity: 0.25,
|
|
163
|
-
shadowRadius: 3.84,
|
|
164
|
-
},
|
|
165
|
-
circleButton: {
|
|
166
|
-
width: 60,
|
|
167
|
-
height: 60,
|
|
168
|
-
borderRadius: 30,
|
|
169
102
|
},
|
|
170
103
|
pillButton: {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
104
|
+
borderRadius: 20,
|
|
105
|
+
},
|
|
106
|
+
strokedButton: {
|
|
107
|
+
backgroundColor: 'transparent',
|
|
108
|
+
borderWidth: 1,
|
|
109
|
+
borderColor: '#000',
|
|
110
|
+
},
|
|
111
|
+
swervButton: {
|
|
112
|
+
transform: [{ rotate: '-2deg' }],
|
|
175
113
|
},
|
|
176
114
|
buttonText: {
|
|
177
|
-
color: '
|
|
178
|
-
marginLeft: 8,
|
|
115
|
+
color: '#fff',
|
|
179
116
|
fontSize: 16,
|
|
180
117
|
fontWeight: '600',
|
|
181
118
|
},
|
|
119
|
+
strokedButtonText: {
|
|
120
|
+
color: '#000',
|
|
121
|
+
},
|
|
122
|
+
customColorText: {
|
|
123
|
+
color: '#fff',
|
|
124
|
+
},
|
|
182
125
|
});
|