react-native-mytatva-rn-sdk 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.
Files changed (35) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +31 -0
  3. package/android/build.gradle +112 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/visitrnsdk/VisitRnSdkPackage.kt +17 -0
  8. package/android/src/main/java/com/visitrnsdk/VisitRnSdkViewManager.kt +20 -0
  9. package/ios/VisitRnSdk.xcodeproj/project.pbxproj +274 -0
  10. package/ios/VisitRnSdkViewManager.h +20 -0
  11. package/ios/VisitRnSdkViewManager.m +1240 -0
  12. package/lib/commonjs/Services.js +35 -0
  13. package/lib/commonjs/Services.js.map +1 -0
  14. package/lib/commonjs/constants.js +11 -0
  15. package/lib/commonjs/constants.js.map +1 -0
  16. package/lib/commonjs/index.android.js +518 -0
  17. package/lib/commonjs/index.android.js.map +1 -0
  18. package/lib/commonjs/index.ios.js +313 -0
  19. package/lib/commonjs/index.ios.js.map +1 -0
  20. package/lib/module/Services.js +27 -0
  21. package/lib/module/Services.js.map +1 -0
  22. package/lib/module/constants.js +5 -0
  23. package/lib/module/constants.js.map +1 -0
  24. package/lib/module/index.android.js +508 -0
  25. package/lib/module/index.android.js.map +1 -0
  26. package/lib/module/index.ios.js +304 -0
  27. package/lib/module/index.ios.js.map +1 -0
  28. package/lib/typescript/index.test.d.ts +1 -0
  29. package/lib/typescript/index.test.d.ts.map +1 -0
  30. package/package.json +177 -0
  31. package/react-native-visit-rn-sdk.podspec +42 -0
  32. package/src/Services.js +37 -0
  33. package/src/constants.js +4 -0
  34. package/src/index.android.js +714 -0
  35. package/src/index.ios.js +376 -0
@@ -0,0 +1,376 @@
1
+ import React, {
2
+ useRef,
3
+ useEffect,
4
+ useState,
5
+ useCallback,
6
+ useMemo,
7
+ } from 'react';
8
+ import {
9
+ StyleSheet,
10
+ SafeAreaView,
11
+ NativeModules,
12
+ NativeEventEmitter,
13
+ Linking,
14
+ Platform,
15
+ ActivityIndicator,
16
+ Dimensions,
17
+ } from 'react-native';
18
+ import { EventRegister } from 'react-native-event-listeners';
19
+ import { WebView } from 'react-native-webview';
20
+ import DeviceInfo from 'react-native-device-info';
21
+ import { getWebViewLink, httpClient } from './Services';
22
+ import constants from './constants';
23
+
24
+ const LINKING_ERROR =
25
+ `The package 'react-native-mytatva-rn-sdk' doesn't seem to be linked. Make sure: \n\n` +
26
+ Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
27
+ '- You rebuilt the app after installing the package\n' +
28
+ '- You are not using Expo Go\n';
29
+
30
+ const escapeChars = {
31
+ lt: '<',
32
+ gt: '>',
33
+ quot: '"',
34
+ apos: "'",
35
+ amp: '&',
36
+ };
37
+
38
+ const unescapeHTML = (str) =>
39
+ // modified from underscore.string and string.js
40
+ // eslint-disable-next-line no-useless-escape
41
+ str.replace(/\&([^;]+);/g, (entity, entityCode) => {
42
+ let match;
43
+
44
+ if (entityCode in escapeChars) {
45
+ return escapeChars[entityCode];
46
+ } else if ((match = entityCode.match(/^#x([\da-fA-F]+)$/))) {
47
+ return String.fromCharCode(parseInt(match[1], 16));
48
+ } else if ((match = entityCode.match(/^#(\d+)$/))) {
49
+ return String.fromCharCode(match[1]);
50
+ } else {
51
+ return entity;
52
+ }
53
+ });
54
+
55
+ const visitEvent = 'visit-event';
56
+
57
+ const MyTatvaRnSdkView = ({
58
+ cpsid,
59
+ baseUrl,
60
+ errorBaseUrl,
61
+ token,
62
+ moduleName,
63
+ environment,
64
+ magicLink,
65
+ isLoggingEnabled,
66
+ }) => {
67
+ const [source, setSource] = useState('');
68
+ const [loading, setLoading] = useState(true);
69
+ useEffect(() => {
70
+ if (magicLink?.trim()?.length) {
71
+ setSource(magicLink);
72
+ setLoading(false);
73
+ } else {
74
+ const systemVersion = DeviceInfo.getSystemVersion();
75
+ const version = DeviceInfo.getVersion();
76
+ DeviceInfo.getUniqueId()
77
+ .then((uniqueId) =>
78
+ getWebViewLink(
79
+ baseUrl,
80
+ token,
81
+ cpsid,
82
+ 'iPhone',
83
+ uniqueId,
84
+ version,
85
+ systemVersion,
86
+ environment
87
+ )
88
+ )
89
+ .then((res) => {
90
+ if (res.data?.errorMessage) {
91
+ const { errorMessage } = res.data;
92
+ const errorUrl = `${errorBaseUrl}/star-health?error=${errorMessage}`;
93
+ setSource(errorUrl);
94
+ if (res.data?.errorMessage === 'Please login again') {
95
+ EventRegister.emitEvent(visitEvent, {
96
+ message: 'unauthorized-wellness-access',
97
+ errorMessage: errorMessage,
98
+ });
99
+ }
100
+ if (res.data?.errorMessage.includes('External Server Error')) {
101
+ EventRegister.emitEvent('visit-event', {
102
+ message: 'external-server-error',
103
+ errorMessage: errorMessage,
104
+ });
105
+ }
106
+ } else if (res.data.message === 'success') {
107
+ const magicCode = res.data?.magicCode;
108
+ const responseReferenceId = res.data?.responseReferenceId;
109
+ let finalBaseUrl = '';
110
+ if (magicCode) {
111
+ if (environment.toUpperCase() === 'PROD') {
112
+ finalBaseUrl = constants.PROD_BASE_URL;
113
+ } else {
114
+ finalBaseUrl = constants.STAGE_BASE_URL;
115
+ }
116
+ }
117
+ if (finalBaseUrl && magicCode) {
118
+ let finalUrl = `${finalBaseUrl}=${magicCode}`;
119
+ if (moduleName?.trim()) {
120
+ finalUrl += `&tab=${moduleName}`;
121
+ }
122
+
123
+ if (
124
+ typeof responseReferenceId === 'string' &&
125
+ responseReferenceId.trim().length > 0
126
+ ) {
127
+ finalUrl += `&responseReferenceId=${responseReferenceId}`;
128
+ }
129
+
130
+ setSource(finalUrl);
131
+ }
132
+ } else {
133
+ EventRegister.emitEvent('visit-event', {
134
+ message: 'generate-magic-link-failed',
135
+ errorMessage: `${res.data}`,
136
+ });
137
+ }
138
+ })
139
+ .catch((err) => {
140
+ console.log('getWebViewLink err', { err });
141
+ EventRegister.emitEvent('visit-event', {
142
+ message: 'generate-magic-link-failed',
143
+ errorMessage: `${err}`,
144
+ });
145
+ })
146
+ .finally(() => {
147
+ setLoading(false);
148
+ });
149
+ }
150
+ }, [
151
+ cpsid,
152
+ token,
153
+ baseUrl,
154
+ errorBaseUrl,
155
+ moduleName,
156
+ environment,
157
+ magicLink,
158
+ isLoggingEnabled,
159
+ ]);
160
+
161
+ const MyTatvaRnSdkViewManager = useMemo(
162
+ () =>
163
+ NativeModules.MyTatvaRnSdkViewManager
164
+ ? NativeModules.MyTatvaRnSdkViewManager
165
+ : new Proxy(
166
+ {},
167
+ {
168
+ get() {
169
+ throw new Error(LINKING_ERROR);
170
+ },
171
+ }
172
+ ),
173
+ []
174
+ );
175
+
176
+ const webviewRef = useRef(null);
177
+ const [apiBaseUrl, setApiBaseUrl] = useState('');
178
+ const [authToken, setAuthToken] = useState('');
179
+ const [hasLoadedOnce, setHasLoadedOnce] = useState(false);
180
+
181
+ const callSyncApi = useCallback(
182
+ (data) =>
183
+ httpClient
184
+ .post(`${apiBaseUrl}/users/data-sync`, data, {
185
+ headers: {
186
+ Authorization: authToken,
187
+ },
188
+ })
189
+ .then((res) => console.log('callSyncData response,', res))
190
+ .catch((err) => console.log('callSyncData err,', { err })),
191
+ [apiBaseUrl, authToken]
192
+ );
193
+
194
+ const callEmbellishApi = useCallback(
195
+ (data) =>
196
+ httpClient
197
+ .post(`${apiBaseUrl}/users/embellish-sync`, data, {
198
+ headers: {
199
+ Authorization: authToken,
200
+ },
201
+ })
202
+ .then((res) => console.log('callEmbellishApi response,', res))
203
+ .catch((err) => console.log('callEmbellishApi err,', { err })),
204
+ [apiBaseUrl, authToken]
205
+ );
206
+
207
+ useEffect(() => {
208
+ const apiManagerEmitter = new NativeEventEmitter(MyTatvaRnSdkViewManager);
209
+ const subscription = apiManagerEmitter.addListener(
210
+ 'EventReminder',
211
+ (reminder) => {
212
+ if (reminder?.callSyncData && reminder?.callSyncData?.length) {
213
+ callSyncApi(reminder?.callSyncData[0]);
214
+ }
215
+ if (reminder?.callEmbellishApi && reminder?.callEmbellishApi?.length) {
216
+ callEmbellishApi(reminder?.callEmbellishApi[0]);
217
+ }
218
+ }
219
+ );
220
+ return () => {
221
+ subscription.remove();
222
+ };
223
+ }, [MyTatvaRnSdkViewManager, callEmbellishApi, callSyncApi]);
224
+
225
+ const handleMessage = async (event) => {
226
+ const data = JSON.parse(unescapeHTML(event.nativeEvent.data));
227
+ const {
228
+ method,
229
+ type,
230
+ frequency,
231
+ timestamp,
232
+ // eslint-disable-next-line no-shadow
233
+ apiBaseUrl,
234
+ authtoken,
235
+ googleFitLastSync,
236
+ gfHourlyLastSync,
237
+ url,
238
+ } = data;
239
+ console.log('handleMessage data is', data);
240
+ console.log(unescapeHTML(event.nativeEvent.data));
241
+ switch (method) {
242
+ case 'UPDATE_PLATFORM':
243
+ webviewRef.current?.injectJavaScript('window.setSdkPlatform("IOS")');
244
+ break;
245
+ case 'CONNECT_TO_GOOGLE_FIT':
246
+ if (DeviceInfo.getModel() === 'iPad') {
247
+ console.log('unsupportedHealthKitDevice triggered');
248
+ webviewRef.current?.injectJavaScript(
249
+ 'window.unsupportedHealthKitDevice(true)'
250
+ );
251
+ } else {
252
+ MyTatvaRnSdkViewManager?.connectToAppleHealth((res) => {
253
+ if (res?.sleepTime || res?.numberOfSteps) {
254
+ webviewRef.current?.injectJavaScript(
255
+ `window.updateFitnessPermissions(true,${res?.numberOfSteps},${res?.sleepTime})`
256
+ );
257
+ } else {
258
+ webviewRef.current?.injectJavaScript(
259
+ 'window.updateFitnessPermissions(true,0,0)'
260
+ );
261
+ }
262
+ });
263
+ }
264
+ break;
265
+ case 'GET_DATA_TO_GENERATE_GRAPH':
266
+ MyTatvaRnSdkViewManager?.renderGraph(
267
+ { type, frequency, timestamp },
268
+ (err, results) => {
269
+ if (err) {
270
+ console.log('error initializing Healthkit: ', err);
271
+ return;
272
+ }
273
+ if (results[0]) {
274
+ console.log('results initializing Healthkit: ', results[0]);
275
+ webviewRef.current?.injectJavaScript(`window.${results[0]}`);
276
+ }
277
+ }
278
+ );
279
+ break;
280
+ case 'UPDATE_API_BASE_URL':
281
+ if (!hasLoadedOnce) {
282
+ console.log('apiBaseUrl is,', apiBaseUrl);
283
+ setApiBaseUrl(apiBaseUrl);
284
+ setAuthToken(authtoken);
285
+ MyTatvaRnSdkViewManager?.updateApiUrl({
286
+ googleFitLastSync,
287
+ gfHourlyLastSync,
288
+ });
289
+ setHasLoadedOnce(true);
290
+ }
291
+ break;
292
+
293
+ case 'OPEN_PDF':
294
+ Linking.openURL(url);
295
+ break;
296
+ case 'CLOSE_VIEW':
297
+ break;
298
+ case 'GET_LOCATION_PERMISSIONS':
299
+ webviewRef.current?.injectJavaScript(
300
+ 'window.checkTheGpsPermission(true)'
301
+ );
302
+ break;
303
+
304
+ default:
305
+ break;
306
+ }
307
+ };
308
+
309
+ const { height, width } = Dimensions.get('screen');
310
+ return (
311
+ // eslint-disable-next-line react-native/no-inline-styles
312
+ <SafeAreaView style={{ flex: 1, backgroundColor: 'white', height, width }}>
313
+ {loading ? (
314
+ <LoadingIndicator />
315
+ ) : (
316
+ <WebView
317
+ ref={webviewRef}
318
+ source={{ uri: source }}
319
+ style={styles.webView}
320
+ javascriptEnabled
321
+ onMessage={handleMessage}
322
+ onError={(errorMessage) => {
323
+ EventRegister.emitEvent(visitEvent, {
324
+ message: 'web-view-error',
325
+ errorMessage: errorMessage,
326
+ });
327
+ if (isLoggingEnabled) {
328
+ console.warn('Webview error: ', errorMessage);
329
+ }
330
+ }}
331
+ />
332
+ )}
333
+ </SafeAreaView>
334
+ );
335
+ };
336
+
337
+ const styles = StyleSheet.create({
338
+ webViewContainer: {
339
+ flex: 1,
340
+ backgroundColor: 'white',
341
+ },
342
+ webView: {
343
+ flex: 1,
344
+ },
345
+ });
346
+
347
+ MyTatvaRnSdkView.defaultProps = {
348
+ id: '',
349
+ token: '',
350
+ baseUrl: '',
351
+ errorBaseUrl: '',
352
+ moduleName: '',
353
+ };
354
+
355
+ export default MyTatvaRnSdkView;
356
+
357
+ const LoadingIndicator = () => {
358
+ return (
359
+ <ActivityIndicator
360
+ color="#000"
361
+ size="small"
362
+ // eslint-disable-next-line react-native/no-inline-styles
363
+ style={{
364
+ flex: 1,
365
+ zIndex: 100,
366
+ position: 'absolute',
367
+ backgroundColor: '#fff',
368
+ opacity: 0.4,
369
+ width: '100%',
370
+ height: '100%',
371
+ justifyContent: 'center',
372
+ alignItems: 'center',
373
+ }}
374
+ />
375
+ );
376
+ };