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.
- package/LICENSE +20 -0
- package/README.md +31 -0
- package/android/build.gradle +112 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/visitrnsdk/VisitRnSdkPackage.kt +17 -0
- package/android/src/main/java/com/visitrnsdk/VisitRnSdkViewManager.kt +20 -0
- package/ios/VisitRnSdk.xcodeproj/project.pbxproj +274 -0
- package/ios/VisitRnSdkViewManager.h +20 -0
- package/ios/VisitRnSdkViewManager.m +1240 -0
- package/lib/commonjs/Services.js +35 -0
- package/lib/commonjs/Services.js.map +1 -0
- package/lib/commonjs/constants.js +11 -0
- package/lib/commonjs/constants.js.map +1 -0
- package/lib/commonjs/index.android.js +518 -0
- package/lib/commonjs/index.android.js.map +1 -0
- package/lib/commonjs/index.ios.js +313 -0
- package/lib/commonjs/index.ios.js.map +1 -0
- package/lib/module/Services.js +27 -0
- package/lib/module/Services.js.map +1 -0
- package/lib/module/constants.js +5 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/index.android.js +508 -0
- package/lib/module/index.android.js.map +1 -0
- package/lib/module/index.ios.js +304 -0
- package/lib/module/index.ios.js.map +1 -0
- package/lib/typescript/index.test.d.ts +1 -0
- package/lib/typescript/index.test.d.ts.map +1 -0
- package/package.json +177 -0
- package/react-native-visit-rn-sdk.podspec +42 -0
- package/src/Services.js +37 -0
- package/src/constants.js +4 -0
- package/src/index.android.js +714 -0
- package/src/index.ios.js +376 -0
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
|
2
|
+
import { EventRegister } from 'react-native-event-listeners';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
SafeAreaView,
|
|
6
|
+
NativeModules,
|
|
7
|
+
PermissionsAndroid,
|
|
8
|
+
BackHandler,
|
|
9
|
+
Linking,
|
|
10
|
+
Alert,
|
|
11
|
+
AppState,
|
|
12
|
+
} from 'react-native';
|
|
13
|
+
|
|
14
|
+
import WebView from 'react-native-webview';
|
|
15
|
+
|
|
16
|
+
import LocationEnabler from 'react-native-location-enabler';
|
|
17
|
+
|
|
18
|
+
import DeviceInfo from 'react-native-device-info';
|
|
19
|
+
|
|
20
|
+
import axios from 'axios';
|
|
21
|
+
|
|
22
|
+
import constants from './constants';
|
|
23
|
+
|
|
24
|
+
export const httpClient = axios.create({
|
|
25
|
+
timeout: 60000,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
PRIORITIES: { HIGH_ACCURACY },
|
|
30
|
+
useLocationSettings,
|
|
31
|
+
addListener,
|
|
32
|
+
} = LocationEnabler;
|
|
33
|
+
|
|
34
|
+
const MyTatvaRnSdkView = ({
|
|
35
|
+
cpsid,
|
|
36
|
+
baseUrl,
|
|
37
|
+
errorBaseUrl,
|
|
38
|
+
token,
|
|
39
|
+
moduleName,
|
|
40
|
+
environment,
|
|
41
|
+
magicLink,
|
|
42
|
+
isLoggingEnabled,
|
|
43
|
+
}) => {
|
|
44
|
+
const [source, setSource] = useState('');
|
|
45
|
+
const [appState, setAppState] = useState(AppState.currentState);
|
|
46
|
+
|
|
47
|
+
const [
|
|
48
|
+
showPermissionAlreadyDeniedDialog,
|
|
49
|
+
setShowPermissionAlreadyDeniedDialog,
|
|
50
|
+
] = useState(false);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (isLoggingEnabled) {
|
|
54
|
+
console.log('useEffect ran');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
NativeModules.VisitFitnessModule.initiateSDK(isLoggingEnabled);
|
|
58
|
+
|
|
59
|
+
if ((magicLink?.trim()?.length || 0) > 0) {
|
|
60
|
+
setSource(magicLink);
|
|
61
|
+
} else {
|
|
62
|
+
DeviceInfo.getAndroidId()
|
|
63
|
+
.then((deviceId) => {
|
|
64
|
+
var buildNumber = DeviceInfo.getBuildNumber();
|
|
65
|
+
let systemVersion = DeviceInfo.getSystemVersion();
|
|
66
|
+
let version = DeviceInfo.getVersion();
|
|
67
|
+
|
|
68
|
+
if (isLoggingEnabled) {
|
|
69
|
+
console.log(
|
|
70
|
+
' baseUrl : ' +
|
|
71
|
+
baseUrl +
|
|
72
|
+
'token: ' +
|
|
73
|
+
token +
|
|
74
|
+
' cpsid: ' +
|
|
75
|
+
cpsid +
|
|
76
|
+
' environment: ' +
|
|
77
|
+
environment +
|
|
78
|
+
'buildNumber:' +
|
|
79
|
+
buildNumber +
|
|
80
|
+
' systemVersion:' +
|
|
81
|
+
systemVersion +
|
|
82
|
+
' version : ' +
|
|
83
|
+
version +
|
|
84
|
+
' deviceId',
|
|
85
|
+
deviceId
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var finalEndPoint = `${baseUrl}/partners/v3/generate-magic-link-star-health`;
|
|
90
|
+
|
|
91
|
+
if (isLoggingEnabled) {
|
|
92
|
+
console.log('finalEndPoint: ' + finalEndPoint);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
httpClient
|
|
96
|
+
.post(finalEndPoint, {
|
|
97
|
+
cpsid: cpsid,
|
|
98
|
+
token: token,
|
|
99
|
+
srcClientId: 'Android',
|
|
100
|
+
deviceId: deviceId,
|
|
101
|
+
appVersion: version,
|
|
102
|
+
deviceVersion: systemVersion,
|
|
103
|
+
userEnv: environment,
|
|
104
|
+
})
|
|
105
|
+
.then((response) => {
|
|
106
|
+
let data = response.data;
|
|
107
|
+
// let visitMagicLink = data.result; //@Deprecated. Superseded by magic code usage.
|
|
108
|
+
const errorMessage = data.errorMessage;
|
|
109
|
+
const magicCode = data.magicCode;
|
|
110
|
+
const responseReferenceId = data.responseReferenceId;
|
|
111
|
+
|
|
112
|
+
let finalBaseUrl = '';
|
|
113
|
+
|
|
114
|
+
if (environment.toUpperCase() === 'PROD') {
|
|
115
|
+
finalBaseUrl = constants.PROD_BASE_URL;
|
|
116
|
+
} else {
|
|
117
|
+
finalBaseUrl = constants.STAGE_BASE_URL;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let finalUrl = `${finalBaseUrl}=${magicCode}`;
|
|
121
|
+
|
|
122
|
+
if (data.message === 'success') {
|
|
123
|
+
if ((moduleName?.trim()?.length || 0) > 0) {
|
|
124
|
+
finalUrl += `&tab=${moduleName}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (
|
|
128
|
+
typeof responseReferenceId === 'string' &&
|
|
129
|
+
responseReferenceId.trim().length > 0
|
|
130
|
+
) {
|
|
131
|
+
finalUrl += `&responseReferenceId=${responseReferenceId}`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (isLoggingEnabled) {
|
|
135
|
+
console.log('magicLink: ' + finalUrl);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
setSource(finalUrl);
|
|
139
|
+
} else {
|
|
140
|
+
var errorUrl = `${errorBaseUrl}/star-health?error=${errorMessage}`;
|
|
141
|
+
setSource(errorUrl);
|
|
142
|
+
|
|
143
|
+
if (errorMessage != null) {
|
|
144
|
+
if (errorMessage === 'Please login again') {
|
|
145
|
+
EventRegister.emitEvent('visit-event', {
|
|
146
|
+
message: 'unauthorized-wellness-access',
|
|
147
|
+
errorMessage: errorMessage,
|
|
148
|
+
});
|
|
149
|
+
} else if (errorMessage.includes('External Server Error')) {
|
|
150
|
+
EventRegister.emitEvent('visit-event', {
|
|
151
|
+
message: 'external-server-error',
|
|
152
|
+
errorMessage: errorMessage,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (isLoggingEnabled) {
|
|
158
|
+
console.log(
|
|
159
|
+
'erorMessage: ' +
|
|
160
|
+
data.errorMessage +
|
|
161
|
+
' errorUrl: ' +
|
|
162
|
+
errorUrl
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
.catch((error) => {
|
|
168
|
+
var errorUrl = `${errorBaseUrl}/star-health?error=${error}`;
|
|
169
|
+
setSource(errorUrl);
|
|
170
|
+
|
|
171
|
+
EventRegister.emitEvent('visit-event', {
|
|
172
|
+
message: 'generate-magic-link-failed',
|
|
173
|
+
errorMessage: `${error}`,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (isLoggingEnabled) {
|
|
177
|
+
console.log('error: ' + error);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
})
|
|
181
|
+
.catch((err) => {
|
|
182
|
+
var errorUrl = `${errorBaseUrl}/star-health?error=${err}`;
|
|
183
|
+
setSource(errorUrl);
|
|
184
|
+
|
|
185
|
+
EventRegister.emitEvent('visit-event', {
|
|
186
|
+
message: 'getDeviceInfo-failed',
|
|
187
|
+
errorMessage: `${err}`,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (isLoggingEnabled) {
|
|
191
|
+
console.log('getDeviceInfo err', err);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}, [
|
|
196
|
+
cpsid,
|
|
197
|
+
token,
|
|
198
|
+
baseUrl,
|
|
199
|
+
errorBaseUrl,
|
|
200
|
+
moduleName,
|
|
201
|
+
environment,
|
|
202
|
+
magicLink,
|
|
203
|
+
isLoggingEnabled,
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
const subscription = AppState.addEventListener(
|
|
208
|
+
'change',
|
|
209
|
+
handleAppStateChange
|
|
210
|
+
);
|
|
211
|
+
console.log(`AppState.addEventListener added, current state: ${appState}`);
|
|
212
|
+
|
|
213
|
+
return () => {
|
|
214
|
+
subscription.remove();
|
|
215
|
+
};
|
|
216
|
+
}, [appState]); // Include appState in the dependency array to ensure it's up to date.
|
|
217
|
+
|
|
218
|
+
const handleAppStateChange = (nextAppState) => {
|
|
219
|
+
// console.log(
|
|
220
|
+
// "nextAppState: " + nextAppState + ", previousState: " + appState
|
|
221
|
+
// );
|
|
222
|
+
|
|
223
|
+
// Instead of relying on the old appState, use the nextAppState directly
|
|
224
|
+
if (appState.match(/inactive|background/) && nextAppState === 'active') {
|
|
225
|
+
if (isLoggingEnabled) {
|
|
226
|
+
console.log('App has come to the foreground!');
|
|
227
|
+
}
|
|
228
|
+
getHealthConnectStatus();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
setAppState(nextAppState); // Update the state with the new app state
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const [enabled, requestResolution] = useLocationSettings(
|
|
235
|
+
{
|
|
236
|
+
priority: HIGH_ACCURACY, // default BALANCED_POWER_ACCURACY
|
|
237
|
+
alwaysShow: true, // default false
|
|
238
|
+
needBle: true, // default false
|
|
239
|
+
},
|
|
240
|
+
false /* optional: default undefined */
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const webviewRef = useRef(null);
|
|
244
|
+
|
|
245
|
+
const showLocationPermissionAlert = () => {
|
|
246
|
+
Alert.alert(
|
|
247
|
+
'Permission Required',
|
|
248
|
+
'Allow location permission from app settings',
|
|
249
|
+
[
|
|
250
|
+
{
|
|
251
|
+
text: 'Cancel',
|
|
252
|
+
onPress: () => {
|
|
253
|
+
console.log('Cancel clicked');
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
text: 'Go to Settings',
|
|
258
|
+
onPress: () => {
|
|
259
|
+
Linking.openSettings();
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
]
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const requestLocationPermission = async () => {
|
|
267
|
+
try {
|
|
268
|
+
console.log('requestLocationPermission called');
|
|
269
|
+
|
|
270
|
+
const isLocationPermissionPresent = await PermissionsAndroid.check(
|
|
271
|
+
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
console.log(
|
|
275
|
+
'isLocationPermissionPresent: ' +
|
|
276
|
+
isLocationPermissionPresent +
|
|
277
|
+
' showPermissionAlreadyDeniedDialog: ' +
|
|
278
|
+
showPermissionAlreadyDeniedDialog
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
if (!isLocationPermissionPresent && showPermissionAlreadyDeniedDialog) {
|
|
282
|
+
console.log('showLocationPermissionAlert() called');
|
|
283
|
+
|
|
284
|
+
showLocationPermissionAlert();
|
|
285
|
+
} else {
|
|
286
|
+
console.log('requesting location permission');
|
|
287
|
+
|
|
288
|
+
const granted = await PermissionsAndroid.request(
|
|
289
|
+
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
|
290
|
+
{
|
|
291
|
+
title: 'Need Location Permission',
|
|
292
|
+
message: 'Need access to location permission',
|
|
293
|
+
buttonNeutral: 'Ask Me Later',
|
|
294
|
+
buttonNegative: 'Cancel',
|
|
295
|
+
buttonPositive: 'OK',
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
|
|
299
|
+
if (isLoggingEnabled) {
|
|
300
|
+
console.log('Location permission granted');
|
|
301
|
+
}
|
|
302
|
+
setShowPermissionAlreadyDeniedDialog(false);
|
|
303
|
+
|
|
304
|
+
if (!enabled) {
|
|
305
|
+
requestResolution();
|
|
306
|
+
} else {
|
|
307
|
+
var finalString = `window.checkTheGpsPermission(true)`;
|
|
308
|
+
console.log('requestLocationPermission: ' + finalString);
|
|
309
|
+
|
|
310
|
+
webviewRef.current?.injectJavaScript(finalString);
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
setShowPermissionAlreadyDeniedDialog(true);
|
|
314
|
+
console.log('Location permission denied');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
} catch (e) {
|
|
318
|
+
console.error(e);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const showHealthConnectPermissionDeniedDialog = () => {
|
|
323
|
+
Alert.alert(
|
|
324
|
+
'Permission Denied',
|
|
325
|
+
'Go to Health Connect App to allow app permission',
|
|
326
|
+
[
|
|
327
|
+
{
|
|
328
|
+
text: 'Cancel',
|
|
329
|
+
onPress: () => {
|
|
330
|
+
console.log('Cancel clicked');
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
text: 'Open Health Connect',
|
|
335
|
+
onPress: () => {
|
|
336
|
+
openHealthConnectApp();
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
]
|
|
340
|
+
);
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const openHealthConnectApp = async () => {
|
|
344
|
+
NativeModules.VisitFitnessModule.openHealthConnectApp();
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
const askForHealthConnectPermission = async () => {
|
|
348
|
+
try {
|
|
349
|
+
const isPermissionGranted =
|
|
350
|
+
await NativeModules.VisitFitnessModule.askForFitnessPermission();
|
|
351
|
+
|
|
352
|
+
if (isLoggingEnabled) {
|
|
353
|
+
console.log('isPermissionGranted: ' + isPermissionGranted);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (isPermissionGranted === 'GRANTED') {
|
|
357
|
+
getHealthConnectStatus();
|
|
358
|
+
// getDailyFitnessData();
|
|
359
|
+
} else if (isPermissionGranted === 'CANCELLED') {
|
|
360
|
+
showHealthConnectPermissionDeniedDialog();
|
|
361
|
+
}
|
|
362
|
+
} catch (e) {
|
|
363
|
+
if (isLoggingEnabled) {
|
|
364
|
+
console.error(e);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const getHealthConnectStatus = async () => {
|
|
370
|
+
try {
|
|
371
|
+
const healthConnectStatus =
|
|
372
|
+
await NativeModules.VisitFitnessModule.getHealthConnectStatus();
|
|
373
|
+
|
|
374
|
+
if (isLoggingEnabled) {
|
|
375
|
+
console.log('getHealthConnectStatus: ' + healthConnectStatus);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (healthConnectStatus === 'NOT_SUPPORTED') {
|
|
379
|
+
webviewRef.current?.injectJavaScript(
|
|
380
|
+
'window.healthConnectNotSupported()'
|
|
381
|
+
);
|
|
382
|
+
} else if (healthConnectStatus === 'NOT_INSTALLED') {
|
|
383
|
+
webviewRef.current?.injectJavaScript(
|
|
384
|
+
'window.healthConnectNotInstall()'
|
|
385
|
+
);
|
|
386
|
+
webviewRef.current?.injectJavaScript(
|
|
387
|
+
'window.updateFitnessPermissions(false,0,0)'
|
|
388
|
+
);
|
|
389
|
+
} else if (healthConnectStatus === 'INSTALLED') {
|
|
390
|
+
webviewRef.current?.injectJavaScript('window.healthConnectAvailable()');
|
|
391
|
+
|
|
392
|
+
webviewRef.current?.injectJavaScript(
|
|
393
|
+
'window.updateFitnessPermissions(false,0,0)'
|
|
394
|
+
);
|
|
395
|
+
} else if (healthConnectStatus === 'CONNECTED') {
|
|
396
|
+
getDailyFitnessData();
|
|
397
|
+
}
|
|
398
|
+
} catch (e) {
|
|
399
|
+
if (isLoggingEnabled) {
|
|
400
|
+
console.error(e);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
const getDailyFitnessData = async () => {
|
|
406
|
+
if (isLoggingEnabled) {
|
|
407
|
+
console.log('getDailyFitnessData() called');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
const dailyFitnessData =
|
|
412
|
+
await NativeModules.VisitFitnessModule.requestDailyFitnessData();
|
|
413
|
+
|
|
414
|
+
webviewRef.current?.injectJavaScript(dailyFitnessData);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (isLoggingEnabled) {
|
|
417
|
+
console.log(error);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const requestActivityData = async (type, frequency, timeStamp) => {
|
|
423
|
+
if (isLoggingEnabled) {
|
|
424
|
+
console.log('requestActivityData() called');
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
try {
|
|
428
|
+
const graphData =
|
|
429
|
+
await NativeModules.VisitFitnessModule.requestActivityDataFromHealthConnect(
|
|
430
|
+
type,
|
|
431
|
+
frequency,
|
|
432
|
+
timeStamp
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
if (isLoggingEnabled) {
|
|
436
|
+
console.log(`requestActivityData() data: ` + graphData);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
webviewRef.current?.injectJavaScript('window.' + graphData);
|
|
440
|
+
} catch (error) {
|
|
441
|
+
if (isLoggingEnabled) {
|
|
442
|
+
console.log(error);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
const updateApiBaseUrl = async (
|
|
448
|
+
apiBaseUrl,
|
|
449
|
+
authtoken,
|
|
450
|
+
googleFitLastSync,
|
|
451
|
+
gfHourlyLastSync
|
|
452
|
+
) => {
|
|
453
|
+
if (isLoggingEnabled) {
|
|
454
|
+
console.log('updateApiBaseUrl() called.');
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
const message = await NativeModules.VisitFitnessModule.updateApiBaseUrl(
|
|
459
|
+
apiBaseUrl,
|
|
460
|
+
authtoken,
|
|
461
|
+
googleFitLastSync,
|
|
462
|
+
gfHourlyLastSync
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
if (isLoggingEnabled) {
|
|
466
|
+
console.log(message);
|
|
467
|
+
}
|
|
468
|
+
} catch (error) {
|
|
469
|
+
if (isLoggingEnabled) {
|
|
470
|
+
console.log(error);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const runBeforeFirst = `
|
|
476
|
+
window.isNativeApp = true;
|
|
477
|
+
window.platform = "ANDROID";
|
|
478
|
+
window.setSdkPlatform('ANDROID');
|
|
479
|
+
true; // note: this is required, or you'll sometimes get silent failures
|
|
480
|
+
`;
|
|
481
|
+
|
|
482
|
+
const handleMessage = (event) => {
|
|
483
|
+
if (event.nativeEvent.data != null) {
|
|
484
|
+
try {
|
|
485
|
+
if (isLoggingEnabled) {
|
|
486
|
+
console.log('Event :' + event.nativeEvent.data);
|
|
487
|
+
}
|
|
488
|
+
const parsedObject = JSON.parse(event.nativeEvent.data);
|
|
489
|
+
if (parsedObject.method != null) {
|
|
490
|
+
switch (parsedObject.method) {
|
|
491
|
+
case 'GET_HEALTH_CONNECT_STATUS':
|
|
492
|
+
getHealthConnectStatus();
|
|
493
|
+
break;
|
|
494
|
+
case 'CONNECT_TO_GOOGLE_FIT':
|
|
495
|
+
askForHealthConnectPermission();
|
|
496
|
+
break;
|
|
497
|
+
case 'UPDATE_PLATFORM':
|
|
498
|
+
webviewRef.current?.injectJavaScript(
|
|
499
|
+
'window.setSdkPlatform("ANDROID")'
|
|
500
|
+
);
|
|
501
|
+
break;
|
|
502
|
+
case 'UPDATE_API_BASE_URL':
|
|
503
|
+
{
|
|
504
|
+
let apiBaseUrl = parsedObject.apiBaseUrl;
|
|
505
|
+
let authtoken = parsedObject.authtoken;
|
|
506
|
+
|
|
507
|
+
let googleFitLastSync = parsedObject.googleFitLastSync;
|
|
508
|
+
let gfHourlyLastSync = parsedObject.gfHourlyLastSync;
|
|
509
|
+
|
|
510
|
+
if (isLoggingEnabled) {
|
|
511
|
+
console.log(
|
|
512
|
+
'apiBaseUrl: ' +
|
|
513
|
+
'NOT SHOWN' +
|
|
514
|
+
' authtoken: ' +
|
|
515
|
+
'NOT SHOWN' +
|
|
516
|
+
' googleFitLastSync: ' +
|
|
517
|
+
googleFitLastSync +
|
|
518
|
+
' gfHourlyLastSync: ' +
|
|
519
|
+
gfHourlyLastSync
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
updateApiBaseUrl(
|
|
524
|
+
apiBaseUrl,
|
|
525
|
+
authtoken,
|
|
526
|
+
googleFitLastSync,
|
|
527
|
+
gfHourlyLastSync
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
break;
|
|
531
|
+
case 'GET_DATA_TO_GENERATE_GRAPH':
|
|
532
|
+
{
|
|
533
|
+
let type = parsedObject.type;
|
|
534
|
+
let frequency = parsedObject.frequency;
|
|
535
|
+
let timeStamp = parsedObject.timestamp;
|
|
536
|
+
|
|
537
|
+
if (isLoggingEnabled) {
|
|
538
|
+
console.log(
|
|
539
|
+
'type: ' +
|
|
540
|
+
type +
|
|
541
|
+
' frequency:' +
|
|
542
|
+
frequency +
|
|
543
|
+
' timeStamp: ' +
|
|
544
|
+
timeStamp
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
requestActivityData(type, frequency, timeStamp);
|
|
549
|
+
}
|
|
550
|
+
break;
|
|
551
|
+
case 'GET_LOCATION_PERMISSIONS':
|
|
552
|
+
console.log('GET_LOCATION_PERMISSIONS');
|
|
553
|
+
requestLocationPermission();
|
|
554
|
+
break;
|
|
555
|
+
case 'OPEN_PDF':
|
|
556
|
+
{
|
|
557
|
+
let pdfUrl = parsedObject.url;
|
|
558
|
+
// console.log("pdfUrl "+pdfUrl);
|
|
559
|
+
|
|
560
|
+
Linking.openURL(pdfUrl);
|
|
561
|
+
}
|
|
562
|
+
break;
|
|
563
|
+
case 'CLOSE_VIEW':
|
|
564
|
+
break;
|
|
565
|
+
|
|
566
|
+
default:
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
} catch (exception) {
|
|
571
|
+
console.log('Exception occured:' + exception.message);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const [canGoBack, setCanGoBack] = useState(false);
|
|
577
|
+
|
|
578
|
+
const handleBack = useCallback(() => {
|
|
579
|
+
if (canGoBack && webviewRef.current) {
|
|
580
|
+
webviewRef.current?.goBack();
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
return false;
|
|
584
|
+
}, [canGoBack]);
|
|
585
|
+
|
|
586
|
+
useEffect(() => {
|
|
587
|
+
const gpsListener = addListener(({ locationEnabled }) => {
|
|
588
|
+
if (locationEnabled) {
|
|
589
|
+
checkLocationPermissionAndSendCallback();
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
BackHandler.addEventListener('hardwareBackPress', handleBack);
|
|
594
|
+
return () => {
|
|
595
|
+
BackHandler.removeEventListener('hardwareBackPress', handleBack);
|
|
596
|
+
gpsListener.remove();
|
|
597
|
+
};
|
|
598
|
+
}, [handleBack]);
|
|
599
|
+
|
|
600
|
+
const checkLocationPermissionAndSendCallback = async () => {
|
|
601
|
+
const isLocationPermissionAvailable = await PermissionsAndroid.check(
|
|
602
|
+
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
if (isLoggingEnabled) {
|
|
606
|
+
console.log(
|
|
607
|
+
'checkLocationPermissionAndSendCallback() isLocationPermissionAvailable: ' +
|
|
608
|
+
isLocationPermissionAvailable +
|
|
609
|
+
'isGPSPermissionAvailabe: true'
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (isLocationPermissionAvailable) {
|
|
614
|
+
var finalString = `window.checkTheGpsPermission(true)`;
|
|
615
|
+
|
|
616
|
+
console.log('listener: ' + finalString);
|
|
617
|
+
|
|
618
|
+
webviewRef.current?.injectJavaScript(finalString);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
return (
|
|
623
|
+
// eslint-disable-next-line react-native/no-inline-styles
|
|
624
|
+
<SafeAreaView style={{ flex: 1 }}>
|
|
625
|
+
{source ? (
|
|
626
|
+
<WebView
|
|
627
|
+
ref={webviewRef}
|
|
628
|
+
source={{
|
|
629
|
+
uri: source,
|
|
630
|
+
headers: {
|
|
631
|
+
platform: 'ANDROID',
|
|
632
|
+
},
|
|
633
|
+
}}
|
|
634
|
+
onMessage={handleMessage}
|
|
635
|
+
injectedJavaScriptBeforeContentLoaded={runBeforeFirst}
|
|
636
|
+
javaScriptEnabled={true}
|
|
637
|
+
onLoadProgress={(event) => setCanGoBack(event.nativeEvent.canGoBack)}
|
|
638
|
+
onError={(errorMessage) => {
|
|
639
|
+
EventRegister.emitEvent('visit-event', {
|
|
640
|
+
message: 'web-view-error',
|
|
641
|
+
errorMessage: errorMessage,
|
|
642
|
+
});
|
|
643
|
+
if (isLoggingEnabled) {
|
|
644
|
+
console.warn('Webview error: ', errorMessage);
|
|
645
|
+
}
|
|
646
|
+
}}
|
|
647
|
+
/>
|
|
648
|
+
) : null}
|
|
649
|
+
</SafeAreaView>
|
|
650
|
+
);
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
export const fetchDailyFitnessData = (startTimeStamp, isLoggingEnabled) => {
|
|
654
|
+
return new Promise((resolve, reject) => {
|
|
655
|
+
console.log('fetchDailyFitnessData called: ' + startTimeStamp);
|
|
656
|
+
|
|
657
|
+
NativeModules.VisitFitnessModule.fetchDailyFitnessData(startTimeStamp)
|
|
658
|
+
.then((result) => {
|
|
659
|
+
resolve(result);
|
|
660
|
+
})
|
|
661
|
+
.catch((err) => reject(err));
|
|
662
|
+
});
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
export const fetchHourlyFitnessData = (startTimeStamp, isLoggingEnabled) => {
|
|
666
|
+
return new Promise((resolve, reject) => {
|
|
667
|
+
if (isLoggingEnabled) {
|
|
668
|
+
console.log('fetchHourlyFitnessData called: ' + startTimeStamp);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
NativeModules.VisitFitnessModule.fetchHourlyFitnessData(startTimeStamp)
|
|
672
|
+
.then((result) => {
|
|
673
|
+
resolve(result);
|
|
674
|
+
})
|
|
675
|
+
.catch((err) => reject(err));
|
|
676
|
+
});
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
// debounce, deferred
|
|
680
|
+
// function debounce(task, ms) {
|
|
681
|
+
// let t = { promise: null, cancel: (_) => void 0 };
|
|
682
|
+
// return async (...args) => {
|
|
683
|
+
// try {
|
|
684
|
+
// t.cancel();
|
|
685
|
+
// t = deferred(ms);
|
|
686
|
+
// await t.promise;
|
|
687
|
+
// await task(...args);
|
|
688
|
+
// } catch (_) {
|
|
689
|
+
// console.log('cleaning up cancelled promise');
|
|
690
|
+
// }
|
|
691
|
+
// };
|
|
692
|
+
// }
|
|
693
|
+
|
|
694
|
+
// function deferred(ms) {
|
|
695
|
+
// let cancel,
|
|
696
|
+
// promise = new Promise((resolve, reject) => {
|
|
697
|
+
// cancel = reject;
|
|
698
|
+
// setTimeout(resolve, ms);
|
|
699
|
+
// });
|
|
700
|
+
// return { promise, cancel };
|
|
701
|
+
// }
|
|
702
|
+
|
|
703
|
+
export default MyTatvaRnSdkView;
|
|
704
|
+
|
|
705
|
+
MyTatvaRnSdkView.defaultProps = {
|
|
706
|
+
cpsid: '',
|
|
707
|
+
token: '',
|
|
708
|
+
baseUrl: '',
|
|
709
|
+
errorBaseUrl: '',
|
|
710
|
+
moduleName: '',
|
|
711
|
+
environment: '',
|
|
712
|
+
magicLink: '',
|
|
713
|
+
isLoggingEnabled: false,
|
|
714
|
+
};
|