partner_react_native_sdk 0.1.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 (94) hide show
  1. package/LICENSE +20 -0
  2. package/PartnerReactNativeSdk.podspec +26 -0
  3. package/README.md +14 -0
  4. package/android/build.gradle +100 -0
  5. package/android/generated/java/com/partnerreactnativesdk/NativePartnerReactNativeSdkSpec.java +37 -0
  6. package/android/generated/jni/CMakeLists.txt +36 -0
  7. package/android/generated/jni/RNPartnerReactNativeSdkSpec-generated.cpp +32 -0
  8. package/android/generated/jni/RNPartnerReactNativeSdkSpec.h +31 -0
  9. package/android/generated/jni/react/renderer/components/RNPartnerReactNativeSdkSpec/RNPartnerReactNativeSdkSpecJSI-generated.cpp +28 -0
  10. package/android/generated/jni/react/renderer/components/RNPartnerReactNativeSdkSpec/RNPartnerReactNativeSdkSpecJSI.h +71 -0
  11. package/android/gradle.properties +5 -0
  12. package/android/src/main/AndroidManifest.xml +3 -0
  13. package/android/src/main/AndroidManifestNew.xml +2 -0
  14. package/android/src/main/java/com/partnerreactnativesdk/PartnerReactNativeSdkModule.kt +23 -0
  15. package/android/src/main/java/com/partnerreactnativesdk/PartnerReactNativeSdkPackage.kt +33 -0
  16. package/ios/PartnerReactNativeSdk.h +6 -0
  17. package/ios/PartnerReactNativeSdk.mm +18 -0
  18. package/ios/generated/RNPartnerReactNativeSdkSpec/RNPartnerReactNativeSdkSpec-generated.mm +39 -0
  19. package/ios/generated/RNPartnerReactNativeSdkSpec/RNPartnerReactNativeSdkSpec.h +63 -0
  20. package/ios/generated/RNPartnerReactNativeSdkSpecJSI-generated.cpp +28 -0
  21. package/ios/generated/RNPartnerReactNativeSdkSpecJSI.h +71 -0
  22. package/lib/module/NativePartnerReactNativeSdk.ts +8 -0
  23. package/lib/module/helpers/ServiceNames.js +132 -0
  24. package/lib/module/helpers/ServiceNames.js.map +1 -0
  25. package/lib/module/helpers/helper.js +4 -0
  26. package/lib/module/helpers/helper.js.map +1 -0
  27. package/lib/module/helpers/network/APICall.js +41 -0
  28. package/lib/module/helpers/network/APICall.js.map +1 -0
  29. package/lib/module/helpers/network/network_manager.js +112 -0
  30. package/lib/module/helpers/network/network_manager.js.map +1 -0
  31. package/lib/module/helpers/partner_library_react_native.js +197 -0
  32. package/lib/module/helpers/partner_library_react_native.js.map +1 -0
  33. package/lib/module/helpers/utils/Constants.js +12 -0
  34. package/lib/module/helpers/utils/Constants.js.map +1 -0
  35. package/lib/module/helpers/utils/LibraryConstants.js +115 -0
  36. package/lib/module/helpers/utils/LibraryConstants.js.map +1 -0
  37. package/lib/module/helpers/utils/deviceInfoManager.js +39 -0
  38. package/lib/module/helpers/utils/deviceInfoManager.js.map +1 -0
  39. package/lib/module/helpers/utils/headerManager.js +21 -0
  40. package/lib/module/helpers/utils/headerManager.js.map +1 -0
  41. package/lib/module/helpers/utils/themeManager.js +40 -0
  42. package/lib/module/helpers/utils/themeManager.js.map +1 -0
  43. package/lib/module/helpers/utils/webviewCallback.js +20 -0
  44. package/lib/module/helpers/utils/webviewCallback.js.map +1 -0
  45. package/lib/module/helpers/webview.js +273 -0
  46. package/lib/module/helpers/webview.js.map +1 -0
  47. package/lib/module/index.js +8 -0
  48. package/lib/module/index.js.map +1 -0
  49. package/lib/module/package.json +1 -0
  50. package/lib/typescript/package.json +1 -0
  51. package/lib/typescript/src/NativePartnerReactNativeSdk.d.ts +7 -0
  52. package/lib/typescript/src/NativePartnerReactNativeSdk.d.ts.map +1 -0
  53. package/lib/typescript/src/helpers/ServiceNames.d.ts +50 -0
  54. package/lib/typescript/src/helpers/ServiceNames.d.ts.map +1 -0
  55. package/lib/typescript/src/helpers/helper.d.ts +1 -0
  56. package/lib/typescript/src/helpers/helper.d.ts.map +1 -0
  57. package/lib/typescript/src/helpers/network/APICall.d.ts +12 -0
  58. package/lib/typescript/src/helpers/network/APICall.d.ts.map +1 -0
  59. package/lib/typescript/src/helpers/network/network_manager.d.ts +21 -0
  60. package/lib/typescript/src/helpers/network/network_manager.d.ts.map +1 -0
  61. package/lib/typescript/src/helpers/partner_library_react_native.d.ts +23 -0
  62. package/lib/typescript/src/helpers/partner_library_react_native.d.ts.map +1 -0
  63. package/lib/typescript/src/helpers/utils/Constants.d.ts +10 -0
  64. package/lib/typescript/src/helpers/utils/Constants.d.ts.map +1 -0
  65. package/lib/typescript/src/helpers/utils/LibraryConstants.d.ts +24 -0
  66. package/lib/typescript/src/helpers/utils/LibraryConstants.d.ts.map +1 -0
  67. package/lib/typescript/src/helpers/utils/deviceInfoManager.d.ts +4 -0
  68. package/lib/typescript/src/helpers/utils/deviceInfoManager.d.ts.map +1 -0
  69. package/lib/typescript/src/helpers/utils/headerManager.d.ts +5 -0
  70. package/lib/typescript/src/helpers/utils/headerManager.d.ts.map +1 -0
  71. package/lib/typescript/src/helpers/utils/themeManager.d.ts +12 -0
  72. package/lib/typescript/src/helpers/utils/themeManager.d.ts.map +1 -0
  73. package/lib/typescript/src/helpers/utils/webviewCallback.d.ts +13 -0
  74. package/lib/typescript/src/helpers/utils/webviewCallback.d.ts.map +1 -0
  75. package/lib/typescript/src/helpers/webview.d.ts +21 -0
  76. package/lib/typescript/src/helpers/webview.d.ts.map +1 -0
  77. package/lib/typescript/src/index.d.ts +5 -0
  78. package/lib/typescript/src/index.d.ts.map +1 -0
  79. package/package.json +187 -0
  80. package/react-native.config.js +12 -0
  81. package/src/NativePartnerReactNativeSdk.ts +8 -0
  82. package/src/helpers/ServiceNames.tsx +166 -0
  83. package/src/helpers/helper.tsx +1 -0
  84. package/src/helpers/network/APICall.tsx +65 -0
  85. package/src/helpers/network/network_manager.tsx +122 -0
  86. package/src/helpers/partner_library_react_native.tsx +279 -0
  87. package/src/helpers/utils/Constants.tsx +10 -0
  88. package/src/helpers/utils/LibraryConstants.tsx +133 -0
  89. package/src/helpers/utils/deviceInfoManager.tsx +37 -0
  90. package/src/helpers/utils/headerManager.tsx +22 -0
  91. package/src/helpers/utils/themeManager.tsx +51 -0
  92. package/src/helpers/utils/webviewCallback.tsx +25 -0
  93. package/src/helpers/webview.tsx +343 -0
  94. package/src/index.tsx +9 -0
@@ -0,0 +1,65 @@
1
+ import NetworkManager from './network_manager';
2
+ import { HeaderManager } from '../utils/headerManager';
3
+
4
+
5
+ export class APICall {
6
+
7
+ private networkManager: NetworkManager = new NetworkManager;
8
+ private headerManager: HeaderManager = new HeaderManager;
9
+
10
+
11
+ async callAPI(
12
+ method: string,
13
+ apiUrl: string,
14
+ options?: {
15
+ body?: Record<string, any>;
16
+ headers?: Record<string, any>;
17
+ encrypted?: boolean;
18
+
19
+ }
20
+ ): Promise<any> {
21
+ const { body, headers, encrypted = false } = options || {};
22
+
23
+ try {
24
+ const response = encrypted
25
+ ? await this._callAPIEncrypt(method, apiUrl, body, headers)
26
+ : await this._callAPIRaw(method, apiUrl, body, headers);
27
+
28
+ return response;
29
+ } catch (error) {
30
+ console.log("Error in callAPI:", error);
31
+ throw error;
32
+ }
33
+ }
34
+
35
+
36
+ private async _callAPIRaw(
37
+ method: string,
38
+ apiUrl: string,
39
+ body?: Record<string, any>,
40
+ headers?: Record<string, any>
41
+ ): Promise<any> {
42
+ const mergedHeaders = {
43
+ ...(await this.headerManager.generateHeaders()),
44
+ ...(headers || {}),
45
+ };
46
+
47
+ return this.networkManager.request({
48
+ url: apiUrl,
49
+ method: method,
50
+ body: body,
51
+ headers: mergedHeaders
52
+ });
53
+ }
54
+
55
+ // TODO: Implement encryption logic
56
+ private async _callAPIEncrypt(
57
+ method: string,
58
+ apiUrl: string,
59
+ body?: Record<string, any>,
60
+ headers?: Record<string, any>
61
+ ): Promise<any> {
62
+ // Encryption logic not implemented, fallback to raw
63
+ return this._callAPIRaw(method, apiUrl, body, headers);
64
+ }
65
+ }
@@ -0,0 +1,122 @@
1
+ import axios, { type AxiosInstance, type AxiosResponse, type AxiosRequestConfig } from 'axios';
2
+
3
+ class NetworkManager {
4
+ private static _instance: NetworkManager = new NetworkManager();
5
+ private _axios: AxiosInstance;
6
+
7
+ constructor() {
8
+ this._axios = axios.create();
9
+ }
10
+
11
+ static getInstance(): NetworkManager {
12
+ return NetworkManager._instance;
13
+ }
14
+
15
+ async request({
16
+ url,
17
+ method,
18
+ body,
19
+ headers,
20
+ options,
21
+ }: {
22
+ url: string;
23
+ method: string;
24
+ body?: Record<string, any>;
25
+ headers?: Record<string, any>;
26
+ options?: AxiosRequestConfig;
27
+ }): Promise<AxiosResponse | null> {
28
+ try {
29
+ headers = headers || {};
30
+ options = options || { headers };
31
+
32
+ let response: AxiosResponse;
33
+ const config: AxiosRequestConfig = {
34
+ ...options,
35
+ headers,
36
+ };
37
+
38
+ switch (method.toUpperCase()) {
39
+ case 'POST':
40
+ response = await this._axios.post(url, body, config);
41
+ break;
42
+ case 'GET':
43
+ response = await this._axios.get(url, config);
44
+ break;
45
+ case 'PUT':
46
+ response = await this._axios.put(url, body, config);
47
+ break;
48
+ case 'PATCH':
49
+ response = await this._axios.patch(url, body, config);
50
+ break;
51
+ case 'DELETE':
52
+ response = await this._axios.delete(url, {
53
+ ...config,
54
+ data: body,
55
+ });
56
+ break;
57
+ default:
58
+ throw new Error(`Method not supported: ${method}`);
59
+ }
60
+
61
+ return response;
62
+ } catch (error) {
63
+ if (__DEV__) {
64
+ if (axios.isAxiosError(error)) {
65
+ if (!error.response) {
66
+ console.log("Network error:", error.message);
67
+ }
68
+ return error.response || null;
69
+ } else {
70
+ console.log("Unexpected error during network request:", error);
71
+ }
72
+ }
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ async get(
78
+ url: string,
79
+ headers?: Record<string, any>,
80
+ options?: AxiosRequestConfig
81
+ ): Promise<AxiosResponse | null> {
82
+ return this.request({ url, method: 'GET', headers, options });
83
+ }
84
+
85
+ async post(
86
+ url: string,
87
+ body: Record<string, any>,
88
+ headers?: Record<string, any>,
89
+ options?: AxiosRequestConfig
90
+ ): Promise<AxiosResponse | null> {
91
+ return this.request({ url, method: 'POST', body, headers, options });
92
+ }
93
+
94
+ async put(
95
+ url: string,
96
+ body: Record<string, any>,
97
+ headers?: Record<string, any>,
98
+ options?: AxiosRequestConfig
99
+ ): Promise<AxiosResponse | null> {
100
+ return this.request({ url, method: 'PUT', body, headers, options });
101
+ }
102
+
103
+ async patch(
104
+ url: string,
105
+ body: Record<string, any>,
106
+ headers?: Record<string, any>,
107
+ options?: AxiosRequestConfig
108
+ ): Promise<AxiosResponse | null> {
109
+ return this.request({ url, method: 'PATCH', body, headers, options });
110
+ }
111
+
112
+ async delete(
113
+ url: string,
114
+ headers?: Record<string, any>,
115
+ body?: Record<string, any>,
116
+ options?: AxiosRequestConfig
117
+ ): Promise<AxiosResponse | null> {
118
+ return this.request({ url, method: 'DELETE', body, headers, options });
119
+ }
120
+ }
121
+
122
+ export default NetworkManager;
@@ -0,0 +1,279 @@
1
+ import { APICall } from './network/APICall';
2
+ import { DeviceInfoManager } from './utils/deviceInfoManager';
3
+ import { LibraryConstants } from './utils/LibraryConstants';
4
+ import { type WebViewCallbackFunction } from './utils/webviewCallback';
5
+ import { ServiceNames } from './ServiceNames';
6
+ import { Constants } from './utils/Constants';
7
+ import { WebView } from '../helpers/webview';
8
+ import { SafeAreaView } from 'react-native-safe-area-context';
9
+ import { StatusBar } from 'react-native';
10
+ export type { WebViewCallbackFunction } from './utils/webviewCallback';
11
+ type InitOptions = {
12
+ whitelistedDomains: string[];
13
+ deviceBindingEnabled: boolean;
14
+ };
15
+
16
+
17
+ export class PartnerLibrary {
18
+
19
+ private static instance: PartnerLibrary | null = null;
20
+ private static intialized = false;
21
+
22
+ private _apiCall = new APICall();
23
+ static webViewCallback: WebViewCallbackFunction;
24
+
25
+ private constructor() { }
26
+
27
+ static getInstance(): PartnerLibrary {
28
+ if (!PartnerLibrary.instance) {
29
+ PartnerLibrary.instance = new PartnerLibrary();
30
+ }
31
+ return PartnerLibrary.instance;
32
+ }
33
+
34
+ static async init(hostName: string, options: InitOptions = {
35
+ whitelistedDomains: [],
36
+ deviceBindingEnabled: false
37
+ }): Promise<void> {
38
+ // console.log("PartnerLibrary.init - initialized:", PartnerLibrary.intialized);
39
+ if (PartnerLibrary.intialized) return;
40
+
41
+ try {
42
+ // Ensure instance exists before setup
43
+ if (!PartnerLibrary.instance) {
44
+ // console.log("PartnerLibrary.init - creating new instance");
45
+ PartnerLibrary.instance = new PartnerLibrary();
46
+ }
47
+ await PartnerLibrary.instance._setup(hostName, options.whitelistedDomains, options.deviceBindingEnabled);
48
+ PartnerLibrary.intialized = true;
49
+ }
50
+ catch (error) {
51
+ console.error("Initialization failed: ", error);
52
+ throw new Error("Initialization failed");
53
+ }
54
+ }
55
+
56
+ private async _setup(
57
+ hostName: string,
58
+ whitelistedDomains: string[],
59
+ deviceBindingEnabled: boolean
60
+ ): Promise<void> {
61
+
62
+
63
+ LibraryConstants.init({
64
+ host: hostName,
65
+ whitelistedDomains: whitelistedDomains,
66
+ deviceBinding: deviceBindingEnabled
67
+ });
68
+
69
+ }
70
+
71
+ async open(
72
+ module: string,
73
+ token: string,
74
+ WebViewCallbackFunction: WebViewCallbackFunction,
75
+
76
+ ): Promise<React.ReactElement> {
77
+ if (!PartnerLibrary.intialized) {
78
+ throw new Error('PartnerLibrary not initialized. Call init() first.');
79
+ }
80
+ try {
81
+ let bank = "";
82
+
83
+ if (module.includes("banking/")) {
84
+ const startIndex = module.indexOf("banking/") + "banking/".length;
85
+ const temp = module.substring(startIndex);
86
+ const endIndex = temp.indexOf("/");
87
+ bank = endIndex === -1 ? temp : temp.substring(0, endIndex);
88
+ }
89
+
90
+ return this._loginAndNavigateToWebView(module, bank, token, WebViewCallbackFunction);
91
+ } catch (e) {
92
+ console.error('Error opening webview:', e);
93
+ throw e;
94
+ }
95
+ }
96
+
97
+
98
+ private async _checkDeviceBinding(
99
+ bank: string,
100
+ url: string,
101
+ WebViewCallbackFunction: WebViewCallbackFunction,
102
+
103
+ ): Promise<React.ReactElement> {
104
+
105
+ console.log("entered in check device binding")
106
+ if (LibraryConstants.deviceBindingEnabled) {
107
+ // TODO: Build the device binding flow
108
+ return Promise.resolve(<></>);
109
+
110
+ } else {
111
+ console.log("calling setup device session")
112
+
113
+ return this._setupDeviceSession(bank, url, WebViewCallbackFunction);
114
+ }
115
+ }
116
+
117
+ private async _loginAndNavigateToWebView(
118
+ module: string,
119
+ bank: string,
120
+ token: string,
121
+ WebViewCallbackFunction: WebViewCallbackFunction,
122
+
123
+ ): Promise<React.ReactElement> {
124
+ // console.log("PartnerLibrary._loginAndNavigateToWebView - LibraryConstants.hostName:", LibraryConstants.hostName);
125
+ try {
126
+ let tokenResponse: any;
127
+ const url = ServiceNames.LOGIN_URL;
128
+ console.log("url is : ", url)
129
+ tokenResponse = await this._apiCall.callAPI(
130
+ 'POST',
131
+ ServiceNames.LOGIN_URL, {
132
+ body: {
133
+ 'token': token
134
+ }
135
+ }
136
+ );
137
+
138
+ if (tokenResponse?.data?.code === "USER_TOKEN_EXPIRED") {
139
+ console.log("Token expired");
140
+ return Promise.resolve(<></>);
141
+ }
142
+
143
+ if (tokenResponse?.data && 'RATE_LIMIT_USER' in tokenResponse.data) {
144
+ console.log("rate limit user");
145
+ }
146
+
147
+ // console.log("Checking login success condition:", {
148
+ // statusCode: tokenResponse?.statusCode,
149
+ // code: tokenResponse?.data?.code
150
+ // });
151
+
152
+ if (tokenResponse?.data?.code === "USER_LOGIN_SUCCESS") {
153
+ console.log("User login success");
154
+ this.fetchAndSetTheme();
155
+ return this._checkDeviceBinding(bank, module, WebViewCallbackFunction);
156
+ } else {
157
+ console.log("Login not successful. Token Response:", tokenResponse);
158
+ return Promise.resolve(<></>);
159
+ }
160
+
161
+ } catch (e) {
162
+ console.error('Error during login:', e);
163
+ throw e;
164
+ }
165
+
166
+
167
+ }
168
+
169
+ private async _setupDeviceSession(
170
+ bank: string,
171
+ url: string,
172
+ WebViewCallbackFunction: WebViewCallbackFunction,
173
+
174
+ ): Promise<React.ReactElement> {
175
+ try {
176
+ console.log("in setup device session")
177
+
178
+ const deviceInfo = await DeviceInfoManager.getDeviceInfo();
179
+ const appVersion = deviceInfo['app_version'] || 'unknown';
180
+
181
+ if (__DEV__) {
182
+ console.log("Device Info:", deviceInfo);
183
+ console.log("App Version:", appVersion);
184
+ }
185
+ console.log("device uuid is : ", deviceInfo[Constants.DEVICE_UUID]);
186
+
187
+ const response = await this._apiCall.callAPI(
188
+ 'POST',
189
+ ServiceNames.DEVICE_SESSION.params({ "partner": bank }),
190
+ {
191
+ body: {
192
+ [Constants.MANUFACTURER]: deviceInfo[Constants.MANUFACTURER],
193
+ [Constants.MODEL]: deviceInfo[Constants.MODEL],
194
+ [Constants.DEVICE_UUID]: deviceInfo[Constants.DEVICE_UUID],
195
+ [Constants.OS]: deviceInfo[Constants.OS],
196
+ [Constants.OS_VERSION]: deviceInfo[Constants.OS_VERSION],
197
+ [Constants.APP_VERSION]: appVersion,
198
+ }
199
+ }
200
+ );
201
+ //console.log("response from setup device session is : ", response)
202
+ if (response?.data && 'RATE_LIMIT_USER' in response.data) {
203
+ console.log("rate limit user");
204
+ }
205
+
206
+ if (response?.status === 200) {
207
+
208
+ return this._openWebView(url, WebViewCallbackFunction);
209
+ } else {
210
+ console.warn('Error setting up device session:', response);
211
+ return this._openWebView(url, WebViewCallbackFunction);
212
+ }
213
+ } catch (e) {
214
+ console.error('Error setting up device session:', e);
215
+ throw e;
216
+ }
217
+ }
218
+
219
+
220
+
221
+ async _openWebView(
222
+ url: string,
223
+ WebViewCallbackFunction: WebViewCallbackFunction,
224
+ ): Promise<React.ReactElement> {
225
+ console.log("entered in open web view");
226
+ console.log("url is : ", LibraryConstants.hostName + url);
227
+
228
+
229
+ return (
230
+ <SafeAreaView style={{ flex: 1 }}>
231
+ <WebView
232
+ url={LibraryConstants.hostName + url}
233
+ onCallback={WebViewCallbackFunction}
234
+ whitelistedUrls={LibraryConstants.whitelistedDomains}
235
+ hostName={LibraryConstants.hostName}
236
+ onPageFinished={() => console.log('WebView page finished loading')}
237
+ />
238
+ </SafeAreaView>
239
+ );
240
+ }
241
+
242
+ async fetchAndSetTheme(): Promise<void> {
243
+ try {
244
+ console.log("Fetching theme from API");
245
+
246
+ const themeResponse: any = await this._apiCall.callAPI(
247
+ 'GET',
248
+ ServiceNames.THEME_URL
249
+ );
250
+ const theme = themeResponse?.data;
251
+
252
+ if (theme && theme["--color-primary-500"]) {
253
+ const rgbValues = theme["--color-primary-500"].split(" ").map(Number);
254
+ if (rgbValues.length === 3) {
255
+ const [r, g, b] = rgbValues;
256
+
257
+ // Update LibraryConstants color
258
+ LibraryConstants.setPrimaryColorFromRGB(r, g, b);
259
+
260
+ // Set status bar color
261
+
262
+ StatusBar.setBackgroundColor(LibraryConstants.primaryColor);
263
+ StatusBar.setBarStyle('light-content');
264
+
265
+
266
+ console.log("Theme color set successfully:", LibraryConstants.primaryColor);
267
+ } else {
268
+ console.warn("Invalid RGB values in theme response");
269
+ }
270
+ } else {
271
+ console.warn("--color-primary-500 not found in theme response");
272
+ }
273
+ } catch (e) {
274
+ console.error("Error Fetching theme: ", e);
275
+ throw e;
276
+ }
277
+ }
278
+
279
+ }
@@ -0,0 +1,10 @@
1
+ export const Constants = {
2
+
3
+ MANUFACTURER: "manufacturer",
4
+ MODEL: "model",
5
+ OS: "os",
6
+ OS_VERSION: "os_version",
7
+ APP_VERSION: "app_version",
8
+ DEVICE_UUID: "device_uuid",
9
+ PRIMARY_COLOR: "#3F51B5"
10
+ } as const;
@@ -0,0 +1,133 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ interface Color {
4
+ r: number;
5
+ g: number;
6
+ b: number;
7
+ a: number;
8
+ }
9
+
10
+ // interface ColorWithValues extends Color {
11
+ // withValues(params: { red: number; green: number; blue: number; alpha: number }): string;
12
+ // }
13
+
14
+ // Helper function for color handling
15
+ const hexToRgba = (hex: string): Color => {
16
+ const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
17
+
18
+ if (match && match[1] && match[2] && match[3]) {
19
+ return {
20
+ r: parseInt(match[1], 16),
21
+ g: parseInt(match[2], 16),
22
+ b: parseInt(match[3], 16),
23
+ a: 1,
24
+ };
25
+ }
26
+
27
+ return { r: 0, g: 0, b: 0, a: 1 };
28
+ };
29
+
30
+
31
+
32
+ // const rgbaToHex = (color: Color): string => {
33
+ // return `#${color.r.toString(16).padStart(2, '0')}${color.g.toString(16).padStart(2, '0')}${color.b.toString(16).padStart(2, '0')}`;
34
+ // };
35
+
36
+ const rgbaToString = (color: Color): string => {
37
+ return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`;
38
+ };
39
+
40
+ export class LibraryConstants {
41
+
42
+
43
+ static deviceBindingEnabled: boolean = true;
44
+
45
+ // Primary color definition
46
+ private static _primaryColorHex: string = '#037EAB';
47
+ private static _primaryColorObj: Color = hexToRgba('#037EAB');
48
+
49
+ // static get primaryColor(): string {
50
+ // return this._primaryColorHex;
51
+ // }
52
+
53
+ static set primaryColor(value: string) {
54
+ this._primaryColorHex = value;
55
+ this._primaryColorObj = hexToRgba(value);
56
+ }
57
+ private static rgbToHex(r: number, g: number, b: number): string {
58
+ return `#${[r, g, b]
59
+ .map(x => {
60
+ const hex = x.toString(16);
61
+ return hex.length === 1 ? '0' + hex : hex;
62
+ })
63
+ .join('')}`;
64
+ }
65
+
66
+ static setPrimaryColorFromRGB(r: number, g: number, b: number): void {
67
+ this._primaryColorObj = { r, g, b, a: 1 };
68
+ this._primaryColorHex = LibraryConstants.rgbToHex(r, g, b);
69
+ }
70
+
71
+
72
+
73
+
74
+ static secondaryColor: string = '#FFFFFF';
75
+
76
+ // Calculate disabled primary color (with 50% opacity)
77
+ static get primaryColorDisabled(): string {
78
+ return rgbaToString({
79
+ r: this._primaryColorObj.r,
80
+ g: this._primaryColorObj.g,
81
+ b: this._primaryColorObj.b,
82
+ a: 0.5
83
+ });
84
+ }
85
+
86
+ static openExternally: string[] = [""];
87
+ static whitelistedUrlsAndroid: string[] = [];
88
+ static whitelistedUrlsIos: string[] = [];
89
+ static hostName: string = "";
90
+ static whitelistedDomains: string[] = [];
91
+
92
+ static init({
93
+ host,
94
+ // whitelistedAndroid,
95
+ // whitelistedIos,
96
+ whitelistedDomains,
97
+ deviceBinding,
98
+ }: {
99
+ host: string;
100
+ whitelistedDomains: string[]
101
+ // whitelistedAndroid?: string[];
102
+ // whitelistedIos?: string[];
103
+ deviceBinding?: boolean;
104
+ }): void {
105
+ this.hostName = host;
106
+ // if (whitelistedAndroid) this.whitelistedUrlsAndroid = whitelistedAndroid;
107
+ // if (whitelistedIos) this.whitelistedUrlsIos = whitelistedIos;
108
+ this.whitelistedDomains = whitelistedDomains;
109
+ if (deviceBinding !== undefined) this.deviceBindingEnabled = deviceBinding;
110
+ }
111
+
112
+ // Helper method to get whitelisted URLs based on platform
113
+ // static getWhitelistedUrls(): string[] {
114
+ // return Platform.OS === 'ios' ? this.whitelistedUrlsIos : this.whitelistedUrlsAndroid;
115
+ // }
116
+
117
+ static getWhitelistedDomains(): string[] {
118
+ return this.whitelistedDomains;
119
+ }
120
+
121
+ static get primaryColor(): string {
122
+ if (Platform.OS === 'android') {
123
+ return rgbaToString(this._primaryColorObj);
124
+ }
125
+ return this._primaryColorHex;
126
+ }
127
+ static getPrimaryColorWithOpacity(opacity: number): string {
128
+ return rgbaToString({
129
+ ...this._primaryColorObj,
130
+ a: opacity
131
+ });
132
+ }
133
+ }
@@ -0,0 +1,37 @@
1
+ import { Platform } from 'react-native';
2
+ import DeviceInfo from 'react-native-device-info';
3
+ import { Constants } from './Constants';
4
+
5
+ export class DeviceInfoManager {
6
+ static async getDeviceInfo(): Promise<Record<string, string>> {
7
+ if (Platform.OS === 'android') {
8
+ let androidId = 'unknown';
9
+ try {
10
+ androidId = await DeviceInfo.getAndroidId();
11
+ } catch (e) {
12
+ if (__DEV__) {
13
+ console.log('Error getting android id:', e);
14
+ }
15
+ }
16
+ return {
17
+ [Constants.MANUFACTURER]: (await DeviceInfo.getManufacturer()) || 'unknown',
18
+ [Constants.MODEL]: DeviceInfo.getModel() || 'unknown',
19
+ [Constants.OS]: 'android',
20
+ [Constants.OS_VERSION]: DeviceInfo.getSystemVersion() || 'unknown',
21
+ [Constants.APP_VERSION]: DeviceInfo.getVersion() || 'unknown',
22
+ [Constants.DEVICE_UUID]: androidId,
23
+ };
24
+ } else if (Platform.OS === 'ios') {
25
+ return {
26
+ [Constants.MANUFACTURER]: 'Apple',
27
+ [Constants.MODEL]: DeviceInfo.getModel() || 'unknown',
28
+ [Constants.OS]: 'ios',
29
+ [Constants.OS_VERSION]: DeviceInfo.getSystemVersion() || 'unknown',
30
+ [Constants.APP_VERSION]: DeviceInfo.getVersion() || 'unknown',
31
+ [Constants.DEVICE_UUID]: (await DeviceInfo.getUniqueId()) || 'unknown',
32
+ };
33
+ } else {
34
+ throw new Error('Unsupported platform');
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,22 @@
1
+ import { Platform } from 'react-native';
2
+ import DeviceInfo from 'react-native-device-info';
3
+ import { DeviceInfoManager } from './deviceInfoManager';
4
+
5
+ export class HeaderManager {
6
+
7
+ private deviceInfoManager = DeviceInfoManager;
8
+
9
+ async generateHeaders(isEncrypted: boolean = true): Promise<Record<string, string>> {
10
+
11
+ const deviceInfo = await this.deviceInfoManager.getDeviceInfo();
12
+
13
+ return {
14
+ ...deviceInfo,
15
+ app_version: DeviceInfo.getVersion() || 'unknown',
16
+ os: Platform.OS === 'android' ? 'Android' : 'iOS',
17
+ os_version: DeviceInfo.getSystemVersion() || 'unknown',
18
+ ...(isEncrypted && { 'Content-Type': 'application/json;charset=utf-8' })
19
+ };
20
+
21
+ }
22
+ }