@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,196 @@
|
|
|
1
|
+
import * as Keychain from 'react-native-keychain';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import { sha256 } from './crypto';
|
|
4
|
+
const CREDENTIALS_KEY = 'onairos_credentials';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Store credentials securely in the device keychain with optional biometric protection
|
|
8
|
+
*/
|
|
9
|
+
export const storeCredentials = async (credentials, options = {}) => {
|
|
10
|
+
try {
|
|
11
|
+
const {
|
|
12
|
+
useBiometrics = true,
|
|
13
|
+
biometricPrompt
|
|
14
|
+
} = options;
|
|
15
|
+
|
|
16
|
+
// Create a JSON string of the credentials
|
|
17
|
+
const credentialsString = JSON.stringify(credentials);
|
|
18
|
+
|
|
19
|
+
// Configure security options based on platform
|
|
20
|
+
const securityOptions = {
|
|
21
|
+
service: CREDENTIALS_KEY,
|
|
22
|
+
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Add biometric protection if requested
|
|
26
|
+
if (useBiometrics) {
|
|
27
|
+
// iOS specific options
|
|
28
|
+
if (Platform.OS === 'ios') {
|
|
29
|
+
securityOptions.accessControl = Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Android specific options
|
|
33
|
+
if (Platform.OS === 'android') {
|
|
34
|
+
securityOptions.accessControl = Keychain.ACCESS_CONTROL.BIOMETRY_ANY;
|
|
35
|
+
if (biometricPrompt) {
|
|
36
|
+
securityOptions.authenticationType = Keychain.AUTHENTICATION_TYPE.BIOMETRIC;
|
|
37
|
+
securityOptions.authenticationPrompt = {
|
|
38
|
+
title: biometricPrompt.title || 'Biometric Authentication',
|
|
39
|
+
subtitle: biometricPrompt.subtitle,
|
|
40
|
+
description: 'Please authenticate to access your Onairos credentials',
|
|
41
|
+
cancel: 'Cancel'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Store in the secure keychain
|
|
48
|
+
await Keychain.setGenericPassword(credentials.username, credentialsString, securityOptions);
|
|
49
|
+
return true;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Error storing credentials:', error);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Retrieve credentials from secure storage, potentially requiring biometric authentication
|
|
58
|
+
*/
|
|
59
|
+
export const getCredentials = async (options = {}) => {
|
|
60
|
+
try {
|
|
61
|
+
const {
|
|
62
|
+
useBiometrics = true,
|
|
63
|
+
biometricPrompt
|
|
64
|
+
} = options;
|
|
65
|
+
|
|
66
|
+
// Configure security options
|
|
67
|
+
const securityOptions = {
|
|
68
|
+
service: CREDENTIALS_KEY
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Add biometric prompt if required
|
|
72
|
+
if (useBiometrics && biometricPrompt) {
|
|
73
|
+
securityOptions.authenticationPrompt = {
|
|
74
|
+
title: biometricPrompt.title || 'Biometric Authentication',
|
|
75
|
+
subtitle: biometricPrompt.subtitle,
|
|
76
|
+
description: 'Please authenticate to access your Onairos credentials',
|
|
77
|
+
cancel: 'Cancel'
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Retrieve from keychain
|
|
82
|
+
const result = await Keychain.getGenericPassword(securityOptions);
|
|
83
|
+
if (!result) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Parse the stored JSON
|
|
88
|
+
const credentials = JSON.parse(result.password);
|
|
89
|
+
return credentials;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('Error retrieving credentials:', error);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check if the user has stored credentials
|
|
98
|
+
*/
|
|
99
|
+
export const hasCredentials = async () => {
|
|
100
|
+
try {
|
|
101
|
+
const result = await Keychain.getGenericPassword({
|
|
102
|
+
service: CREDENTIALS_KEY
|
|
103
|
+
});
|
|
104
|
+
return !!result;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('Error checking for credentials:', error);
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Delete stored credentials
|
|
113
|
+
*/
|
|
114
|
+
export const deleteCredentials = async () => {
|
|
115
|
+
try {
|
|
116
|
+
await Keychain.resetGenericPassword({
|
|
117
|
+
service: CREDENTIALS_KEY
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error('Error deleting credentials:', error);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Update specific fields in the stored credentials
|
|
128
|
+
*/
|
|
129
|
+
export const updateCredentials = async (updates, options = {}) => {
|
|
130
|
+
try {
|
|
131
|
+
// Get current credentials
|
|
132
|
+
const currentCredentials = await getCredentials(options);
|
|
133
|
+
if (!currentCredentials) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Merge updates with current credentials
|
|
138
|
+
const updatedCredentials = {
|
|
139
|
+
...currentCredentials,
|
|
140
|
+
...updates
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Store updated credentials
|
|
144
|
+
return await storeCredentials(updatedCredentials, options);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('Error updating credentials:', error);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Generate a device-specific unique username
|
|
153
|
+
*/
|
|
154
|
+
export const generateDeviceUsername = async () => {
|
|
155
|
+
try {
|
|
156
|
+
// Get a device-specific identifier that we can use
|
|
157
|
+
// This is a simplified example - in production you might want to use
|
|
158
|
+
// a more robust device identifier method
|
|
159
|
+
const deviceInfo = `${Platform.OS}-${Platform.Version}-${Date.now()}`;
|
|
160
|
+
|
|
161
|
+
// Hash it to create a unique identifier
|
|
162
|
+
const username = `onairos_${sha256(deviceInfo).substring(0, 10)}`;
|
|
163
|
+
return username;
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error('Error generating device username:', error);
|
|
166
|
+
// Fallback to a timestamp-based username if there's an error
|
|
167
|
+
return `onairos_${Date.now().toString(36)}`;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Verify if credentials are valid (not expired, etc.)
|
|
173
|
+
*/
|
|
174
|
+
export const verifyCredentials = async credentials => {
|
|
175
|
+
try {
|
|
176
|
+
// Basic verification - check if credentials exist and aren't too old
|
|
177
|
+
if (!credentials || !credentials.accessToken || !credentials.username) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Check for expiration (example: credentials expire after 30 days)
|
|
182
|
+
const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;
|
|
183
|
+
const isExpired = Date.now() - credentials.createdAt > thirtyDaysMs;
|
|
184
|
+
if (isExpired) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Add any additional verification logic here
|
|
189
|
+
|
|
190
|
+
return true;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('Error verifying credentials:', error);
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=secureStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Keychain","Platform","sha256","CREDENTIALS_KEY","storeCredentials","credentials","options","useBiometrics","biometricPrompt","credentialsString","JSON","stringify","securityOptions","service","accessible","ACCESSIBLE","WHEN_UNLOCKED_THIS_DEVICE_ONLY","OS","accessControl","ACCESS_CONTROL","BIOMETRY_ANY_OR_DEVICE_PASSCODE","BIOMETRY_ANY","authenticationType","AUTHENTICATION_TYPE","BIOMETRIC","authenticationPrompt","title","subtitle","description","cancel","setGenericPassword","username","error","console","getCredentials","result","getGenericPassword","parse","password","hasCredentials","deleteCredentials","resetGenericPassword","updateCredentials","updates","currentCredentials","updatedCredentials","generateDeviceUsername","deviceInfo","Version","Date","now","substring","toString","verifyCredentials","accessToken","thirtyDaysMs","isExpired","createdAt"],"sourceRoot":"..\\..\\..\\src","sources":["utils/secureStorage.ts"],"mappings":"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","ignoreList":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@onairos/react-native",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Onairos React Native SDK for social media authentication and AI model training",
|
|
5
|
+
"main": "lib/commonjs/index",
|
|
6
|
+
"module": "lib/module/index",
|
|
7
|
+
"types": "lib/typescript/index.d.ts",
|
|
8
|
+
"react-native": "src/index",
|
|
9
|
+
"source": "src/index",
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"lib",
|
|
13
|
+
"android",
|
|
14
|
+
"ios",
|
|
15
|
+
"cpp",
|
|
16
|
+
"*.podspec",
|
|
17
|
+
"!lib/typescript/example",
|
|
18
|
+
"!ios/build",
|
|
19
|
+
"!android/build",
|
|
20
|
+
"!android/gradle",
|
|
21
|
+
"!android/gradlew",
|
|
22
|
+
"!android/gradlew.bat",
|
|
23
|
+
"!android/local.properties",
|
|
24
|
+
"!**/__tests__",
|
|
25
|
+
"!**/__fixtures__",
|
|
26
|
+
"!**/__mocks__",
|
|
27
|
+
"!**/.*"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "jest",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
33
|
+
"prepare": "bob build",
|
|
34
|
+
"release": "release-it",
|
|
35
|
+
"example": "yarn --cwd example",
|
|
36
|
+
"bootstrap": "yarn example && yarn install",
|
|
37
|
+
"build": "bob build",
|
|
38
|
+
"clean": "del lib"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"react-native",
|
|
42
|
+
"ios",
|
|
43
|
+
"android",
|
|
44
|
+
"oauth",
|
|
45
|
+
"social-media",
|
|
46
|
+
"authentication",
|
|
47
|
+
"onairos"
|
|
48
|
+
],
|
|
49
|
+
"repository": "https://github.com/onairos/onairos-react-native",
|
|
50
|
+
"author": "Onairos",
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/onairos/onairos-react-native/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/onairos/onairos-react-native#readme",
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public",
|
|
58
|
+
"registry": "https://registry.npmjs.org/"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@gorhom/bottom-sheet": "^4",
|
|
62
|
+
"@react-native-community/netinfo": "^9.0.0",
|
|
63
|
+
"react-native-crypto-js": "^1.0.0",
|
|
64
|
+
"react-native-gesture-handler": "^2.0.0",
|
|
65
|
+
"react-native-keychain": "^8.0.0",
|
|
66
|
+
"react-native-reanimated": "^2.0.0",
|
|
67
|
+
"react-native-rsa-native": "^2.0.0",
|
|
68
|
+
"react-native-safe-area-context": "^4.0.0",
|
|
69
|
+
"react-native-vector-icons": "^9.0.0",
|
|
70
|
+
"react-native-webview": "^11.0.0"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@react-native-community/eslint-config": "^3.0.0",
|
|
74
|
+
"@release-it/conventional-changelog": "^5.0.0",
|
|
75
|
+
"@types/jest": "^28.1.2",
|
|
76
|
+
"@types/react": "^18.0.0",
|
|
77
|
+
"@types/react-native": "^0.70.0",
|
|
78
|
+
"@types/react-native-vector-icons": "^6.4.13",
|
|
79
|
+
"babel-plugin-module-resolver": "^4.1.0",
|
|
80
|
+
"del-cli": "^5.1.0",
|
|
81
|
+
"eslint": "^8.4.1",
|
|
82
|
+
"eslint-config-prettier": "^8.5.0",
|
|
83
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
84
|
+
"jest": "^28.1.1",
|
|
85
|
+
"metro-react-native-babel-preset": "^0.73.10",
|
|
86
|
+
"prettier": "^2.0.5",
|
|
87
|
+
"react": "18.2.0",
|
|
88
|
+
"react-native": "0.71.0",
|
|
89
|
+
"react-native-builder-bob": "^0.20.0",
|
|
90
|
+
"release-it": "^15.0.0",
|
|
91
|
+
"typescript": "^4.5.2"
|
|
92
|
+
},
|
|
93
|
+
"resolutions": {
|
|
94
|
+
"@types/react": "17.0.21"
|
|
95
|
+
},
|
|
96
|
+
"peerDependencies": {
|
|
97
|
+
"react": "*",
|
|
98
|
+
"react-native": "*"
|
|
99
|
+
},
|
|
100
|
+
"jest": {
|
|
101
|
+
"preset": "react-native",
|
|
102
|
+
"modulePathIgnorePatterns": [
|
|
103
|
+
"<rootDir>/example/node_modules",
|
|
104
|
+
"<rootDir>/lib/"
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
"react-native-builder-bob": {
|
|
108
|
+
"source": "src",
|
|
109
|
+
"output": "lib",
|
|
110
|
+
"targets": [
|
|
111
|
+
"commonjs",
|
|
112
|
+
"module"
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
ScrollView,
|
|
8
|
+
Modal,
|
|
9
|
+
} from 'react-native';
|
|
10
|
+
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
11
|
+
import { COLORS, PLATFORMS } from '../constants';
|
|
12
|
+
|
|
13
|
+
interface DataRequestModalProps {
|
|
14
|
+
visible: boolean;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
onAccept: () => void;
|
|
17
|
+
requestData: Record<string, Record<string, string>>;
|
|
18
|
+
AppName: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const DataRequestModal: React.FC<DataRequestModalProps> = ({
|
|
22
|
+
visible,
|
|
23
|
+
onClose,
|
|
24
|
+
onAccept,
|
|
25
|
+
requestData,
|
|
26
|
+
AppName,
|
|
27
|
+
}) => {
|
|
28
|
+
const renderPermissions = () => {
|
|
29
|
+
return Object.entries(requestData).map(([platform, permissions]) => {
|
|
30
|
+
const platformConfig = PLATFORMS[platform];
|
|
31
|
+
if (!platformConfig) return null;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<View key={platform} style={styles.platformContainer}>
|
|
35
|
+
<View style={styles.platformHeader}>
|
|
36
|
+
<Icon name={platformConfig.icon} size={24} color={platformConfig.color} />
|
|
37
|
+
<Text style={styles.platformName}>{platformConfig.name}</Text>
|
|
38
|
+
</View>
|
|
39
|
+
<View style={styles.permissionsContainer}>
|
|
40
|
+
{Object.entries(permissions).map(([key, value]) => (
|
|
41
|
+
<Text key={key} style={styles.permissionText}>
|
|
42
|
+
• {key}: {value}
|
|
43
|
+
</Text>
|
|
44
|
+
))}
|
|
45
|
+
</View>
|
|
46
|
+
</View>
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Modal
|
|
53
|
+
visible={visible}
|
|
54
|
+
transparent
|
|
55
|
+
animationType="slide"
|
|
56
|
+
onRequestClose={onClose}
|
|
57
|
+
>
|
|
58
|
+
<View style={styles.modalOverlay}>
|
|
59
|
+
<View style={styles.modalContent}>
|
|
60
|
+
<View style={styles.header}>
|
|
61
|
+
<Icon name="auto_awesome" size={24} color={COLORS.primary} />
|
|
62
|
+
<Text style={styles.headerTitle}>
|
|
63
|
+
{AppName} Data Request
|
|
64
|
+
</Text>
|
|
65
|
+
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
|
66
|
+
<Icon name="close" size={24} color="#000" />
|
|
67
|
+
</TouchableOpacity>
|
|
68
|
+
</View>
|
|
69
|
+
|
|
70
|
+
<ScrollView style={styles.scrollContent}>
|
|
71
|
+
<Text style={styles.description}>
|
|
72
|
+
{AppName} is requesting access to the following data:
|
|
73
|
+
</Text>
|
|
74
|
+
{renderPermissions()}
|
|
75
|
+
</ScrollView>
|
|
76
|
+
|
|
77
|
+
<View style={styles.footer}>
|
|
78
|
+
<TouchableOpacity
|
|
79
|
+
style={[styles.button, styles.cancelButton]}
|
|
80
|
+
onPress={onClose}
|
|
81
|
+
>
|
|
82
|
+
<Text style={styles.cancelButtonText}>Cancel</Text>
|
|
83
|
+
</TouchableOpacity>
|
|
84
|
+
<TouchableOpacity
|
|
85
|
+
style={[styles.button, styles.acceptButton]}
|
|
86
|
+
onPress={onAccept}
|
|
87
|
+
>
|
|
88
|
+
<Text style={styles.acceptButtonText}>Accept</Text>
|
|
89
|
+
</TouchableOpacity>
|
|
90
|
+
</View>
|
|
91
|
+
</View>
|
|
92
|
+
</View>
|
|
93
|
+
</Modal>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const styles = StyleSheet.create({
|
|
98
|
+
modalOverlay: {
|
|
99
|
+
flex: 1,
|
|
100
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
101
|
+
justifyContent: 'center',
|
|
102
|
+
alignItems: 'center',
|
|
103
|
+
},
|
|
104
|
+
modalContent: {
|
|
105
|
+
backgroundColor: '#fff',
|
|
106
|
+
borderRadius: 16,
|
|
107
|
+
width: '90%',
|
|
108
|
+
maxHeight: '80%',
|
|
109
|
+
overflow: 'hidden',
|
|
110
|
+
},
|
|
111
|
+
header: {
|
|
112
|
+
flexDirection: 'row',
|
|
113
|
+
alignItems: 'center',
|
|
114
|
+
padding: 16,
|
|
115
|
+
backgroundColor: COLORS.headerBg,
|
|
116
|
+
},
|
|
117
|
+
headerTitle: {
|
|
118
|
+
flex: 1,
|
|
119
|
+
fontSize: 18,
|
|
120
|
+
fontWeight: '600',
|
|
121
|
+
marginLeft: 12,
|
|
122
|
+
color: '#000',
|
|
123
|
+
},
|
|
124
|
+
closeButton: {
|
|
125
|
+
padding: 8,
|
|
126
|
+
},
|
|
127
|
+
scrollContent: {
|
|
128
|
+
padding: 16,
|
|
129
|
+
},
|
|
130
|
+
description: {
|
|
131
|
+
fontSize: 16,
|
|
132
|
+
color: COLORS.text.secondary,
|
|
133
|
+
marginBottom: 16,
|
|
134
|
+
},
|
|
135
|
+
platformContainer: {
|
|
136
|
+
marginBottom: 16,
|
|
137
|
+
borderWidth: 1,
|
|
138
|
+
borderColor: COLORS.border,
|
|
139
|
+
borderRadius: 8,
|
|
140
|
+
padding: 12,
|
|
141
|
+
},
|
|
142
|
+
platformHeader: {
|
|
143
|
+
flexDirection: 'row',
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
marginBottom: 8,
|
|
146
|
+
},
|
|
147
|
+
platformName: {
|
|
148
|
+
fontSize: 16,
|
|
149
|
+
fontWeight: '600',
|
|
150
|
+
marginLeft: 8,
|
|
151
|
+
},
|
|
152
|
+
permissionsContainer: {
|
|
153
|
+
marginLeft: 32,
|
|
154
|
+
},
|
|
155
|
+
permissionText: {
|
|
156
|
+
fontSize: 14,
|
|
157
|
+
color: COLORS.text.secondary,
|
|
158
|
+
marginBottom: 4,
|
|
159
|
+
},
|
|
160
|
+
footer: {
|
|
161
|
+
flexDirection: 'row',
|
|
162
|
+
padding: 16,
|
|
163
|
+
borderTopWidth: 1,
|
|
164
|
+
borderTopColor: COLORS.border,
|
|
165
|
+
justifyContent: 'flex-end',
|
|
166
|
+
},
|
|
167
|
+
button: {
|
|
168
|
+
paddingHorizontal: 20,
|
|
169
|
+
paddingVertical: 10,
|
|
170
|
+
borderRadius: 8,
|
|
171
|
+
marginLeft: 12,
|
|
172
|
+
},
|
|
173
|
+
cancelButton: {
|
|
174
|
+
backgroundColor: COLORS.border,
|
|
175
|
+
},
|
|
176
|
+
acceptButton: {
|
|
177
|
+
backgroundColor: COLORS.primary,
|
|
178
|
+
},
|
|
179
|
+
cancelButtonText: {
|
|
180
|
+
color: COLORS.text.secondary,
|
|
181
|
+
fontWeight: '600',
|
|
182
|
+
},
|
|
183
|
+
acceptButtonText: {
|
|
184
|
+
color: '#fff',
|
|
185
|
+
fontWeight: '600',
|
|
186
|
+
},
|
|
187
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, Animated } from 'react-native';
|
|
3
|
+
|
|
4
|
+
const Notification = ({ message, color = 'blue', duration = 3000, onClose }) => {
|
|
5
|
+
const [fadeAnim] = useState(new Animated.Value(0));
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
// Fade in
|
|
9
|
+
Animated.timing(fadeAnim, {
|
|
10
|
+
toValue: 1,
|
|
11
|
+
duration: 300,
|
|
12
|
+
useNativeDriver: true,
|
|
13
|
+
}).start();
|
|
14
|
+
|
|
15
|
+
// Set timeout to fade out
|
|
16
|
+
const timer = setTimeout(() => {
|
|
17
|
+
Animated.timing(fadeAnim, {
|
|
18
|
+
toValue: 0,
|
|
19
|
+
duration: 300,
|
|
20
|
+
useNativeDriver: true,
|
|
21
|
+
}).start(() => {
|
|
22
|
+
if (onClose) onClose();
|
|
23
|
+
});
|
|
24
|
+
}, duration);
|
|
25
|
+
|
|
26
|
+
return () => clearTimeout(timer);
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
// Determine background color based on the color prop
|
|
30
|
+
const getBackgroundColor = () => {
|
|
31
|
+
switch (color) {
|
|
32
|
+
case 'red':
|
|
33
|
+
return '#FFEBEE';
|
|
34
|
+
case 'green':
|
|
35
|
+
return '#E8F5E9';
|
|
36
|
+
case 'yellow':
|
|
37
|
+
return '#FFF8E1';
|
|
38
|
+
default:
|
|
39
|
+
return '#E3F2FD';
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Determine text color based on the color prop
|
|
44
|
+
const getTextColor = () => {
|
|
45
|
+
switch (color) {
|
|
46
|
+
case 'red':
|
|
47
|
+
return '#D32F2F';
|
|
48
|
+
case 'green':
|
|
49
|
+
return '#388E3C';
|
|
50
|
+
case 'yellow':
|
|
51
|
+
return '#F57F17';
|
|
52
|
+
default:
|
|
53
|
+
return '#1976D2';
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Animated.View
|
|
59
|
+
style={[
|
|
60
|
+
styles.container,
|
|
61
|
+
{
|
|
62
|
+
backgroundColor: getBackgroundColor(),
|
|
63
|
+
opacity: fadeAnim,
|
|
64
|
+
transform: [
|
|
65
|
+
{
|
|
66
|
+
translateY: fadeAnim.interpolate({
|
|
67
|
+
inputRange: [0, 1],
|
|
68
|
+
outputRange: [-20, 0],
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
]}
|
|
74
|
+
>
|
|
75
|
+
<Text style={[styles.message, { color: getTextColor() }]}>{message}</Text>
|
|
76
|
+
</Animated.View>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const styles = StyleSheet.create({
|
|
81
|
+
container: {
|
|
82
|
+
position: 'absolute',
|
|
83
|
+
top: 40,
|
|
84
|
+
left: 20,
|
|
85
|
+
right: 20,
|
|
86
|
+
padding: 16,
|
|
87
|
+
borderRadius: 8,
|
|
88
|
+
shadowColor: '#000',
|
|
89
|
+
shadowOffset: { width: 0, height: 2 },
|
|
90
|
+
shadowOpacity: 0.1,
|
|
91
|
+
shadowRadius: 4,
|
|
92
|
+
elevation: 3,
|
|
93
|
+
zIndex: 1000,
|
|
94
|
+
},
|
|
95
|
+
message: {
|
|
96
|
+
fontSize: 16,
|
|
97
|
+
fontWeight: '500',
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export default Notification;
|