banking_dcb_sdk_react_native 0.1.9
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/PartnerReactNativeSdk.podspec +31 -0
- package/README.md +14 -0
- package/android/build.gradle +100 -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/partnerreactnativesdk/PartnerReactNativeSdkModule.kt +23 -0
- package/android/src/main/java/com/partnerreactnativesdk/PartnerReactNativeSdkPackage.kt +33 -0
- package/ios/PartnerReactNativeSdk.h +6 -0
- package/ios/PartnerReactNativeSdk.mm +29 -0
- package/lib/module/helpers/ServiceNames.js +135 -0
- package/lib/module/helpers/ServiceNames.js.map +1 -0
- package/lib/module/helpers/analytics/analytics_event_model.js +37 -0
- package/lib/module/helpers/analytics/analytics_event_model.js.map +1 -0
- package/lib/module/helpers/analytics/analytics_logger.js +73 -0
- package/lib/module/helpers/analytics/analytics_logger.js.map +1 -0
- package/lib/module/helpers/analytics/event_storage.js +35 -0
- package/lib/module/helpers/analytics/event_storage.js.map +1 -0
- package/lib/module/helpers/banking_dcb_react_native.js +297 -0
- package/lib/module/helpers/banking_dcb_react_native.js.map +1 -0
- package/lib/module/helpers/helper.js +4 -0
- package/lib/module/helpers/helper.js.map +1 -0
- package/lib/module/helpers/network/APICall.js +111 -0
- package/lib/module/helpers/network/APICall.js.map +1 -0
- package/lib/module/helpers/network/Encryption.js +148 -0
- package/lib/module/helpers/network/Encryption.js.map +1 -0
- package/lib/module/helpers/network/network_manager.js +112 -0
- package/lib/module/helpers/network/network_manager.js.map +1 -0
- package/lib/module/helpers/utils/Constants.js +12 -0
- package/lib/module/helpers/utils/Constants.js.map +1 -0
- package/lib/module/helpers/utils/LibraryConstants.js +115 -0
- package/lib/module/helpers/utils/LibraryConstants.js.map +1 -0
- package/lib/module/helpers/utils/deviceInfoManager.js +39 -0
- package/lib/module/helpers/utils/deviceInfoManager.js.map +1 -0
- package/lib/module/helpers/utils/headerManager.js +21 -0
- package/lib/module/helpers/utils/headerManager.js.map +1 -0
- package/lib/module/helpers/utils/themeManager.js +40 -0
- package/lib/module/helpers/utils/themeManager.js.map +1 -0
- package/lib/module/helpers/utils/webviewCallback.js +20 -0
- package/lib/module/helpers/utils/webviewCallback.js.map +1 -0
- package/lib/module/helpers/webview.js +314 -0
- package/lib/module/helpers/webview.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/helpers/ServiceNames.d.ts +51 -0
- package/lib/typescript/src/helpers/ServiceNames.d.ts.map +1 -0
- package/lib/typescript/src/helpers/analytics/analytics_event_model.d.ts +16 -0
- package/lib/typescript/src/helpers/analytics/analytics_event_model.d.ts.map +1 -0
- package/lib/typescript/src/helpers/analytics/analytics_logger.d.ts +17 -0
- package/lib/typescript/src/helpers/analytics/analytics_logger.d.ts.map +1 -0
- package/lib/typescript/src/helpers/analytics/event_storage.d.ts +8 -0
- package/lib/typescript/src/helpers/analytics/event_storage.d.ts.map +1 -0
- package/lib/typescript/src/helpers/banking_dcb_react_native.d.ts +33 -0
- package/lib/typescript/src/helpers/banking_dcb_react_native.d.ts.map +1 -0
- package/lib/typescript/src/helpers/helper.d.ts +1 -0
- package/lib/typescript/src/helpers/helper.d.ts.map +1 -0
- package/lib/typescript/src/helpers/network/APICall.d.ts +13 -0
- package/lib/typescript/src/helpers/network/APICall.d.ts.map +1 -0
- package/lib/typescript/src/helpers/network/Encryption.d.ts +24 -0
- package/lib/typescript/src/helpers/network/Encryption.d.ts.map +1 -0
- package/lib/typescript/src/helpers/network/network_manager.d.ts +21 -0
- package/lib/typescript/src/helpers/network/network_manager.d.ts.map +1 -0
- package/lib/typescript/src/helpers/utils/Constants.d.ts +10 -0
- package/lib/typescript/src/helpers/utils/Constants.d.ts.map +1 -0
- package/lib/typescript/src/helpers/utils/LibraryConstants.d.ts +24 -0
- package/lib/typescript/src/helpers/utils/LibraryConstants.d.ts.map +1 -0
- package/lib/typescript/src/helpers/utils/deviceInfoManager.d.ts +4 -0
- package/lib/typescript/src/helpers/utils/deviceInfoManager.d.ts.map +1 -0
- package/lib/typescript/src/helpers/utils/headerManager.d.ts +5 -0
- package/lib/typescript/src/helpers/utils/headerManager.d.ts.map +1 -0
- package/lib/typescript/src/helpers/utils/themeManager.d.ts +12 -0
- package/lib/typescript/src/helpers/utils/themeManager.d.ts.map +1 -0
- package/lib/typescript/src/helpers/utils/webviewCallback.d.ts +13 -0
- package/lib/typescript/src/helpers/utils/webviewCallback.d.ts.map +1 -0
- package/lib/typescript/src/helpers/webview.d.ts +21 -0
- package/lib/typescript/src/helpers/webview.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +170 -0
- package/react-native.config.js +12 -0
- package/src/helpers/ServiceNames.tsx +170 -0
- package/src/helpers/analytics/analytics_event_model.tsx +47 -0
- package/src/helpers/analytics/analytics_logger.tsx +91 -0
- package/src/helpers/analytics/event_storage.tsx +44 -0
- package/src/helpers/banking_dcb_react_native.tsx +413 -0
- package/src/helpers/helper.tsx +1 -0
- package/src/helpers/network/APICall.tsx +154 -0
- package/src/helpers/network/Encryption.tsx +179 -0
- package/src/helpers/network/network_manager.tsx +122 -0
- package/src/helpers/utils/Constants.tsx +10 -0
- package/src/helpers/utils/LibraryConstants.tsx +133 -0
- package/src/helpers/utils/deviceInfoManager.tsx +37 -0
- package/src/helpers/utils/headerManager.tsx +22 -0
- package/src/helpers/utils/themeManager.tsx +51 -0
- package/src/helpers/utils/webviewCallback.tsx +25 -0
- package/src/helpers/webview.tsx +410 -0
- package/src/index.tsx +5 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { WebView as RNWebView } from 'react-native-webview';
|
|
2
|
+
import {
|
|
3
|
+
BackHandler,
|
|
4
|
+
Platform,
|
|
5
|
+
Linking,
|
|
6
|
+
SafeAreaView,
|
|
7
|
+
ActivityIndicator,
|
|
8
|
+
View,
|
|
9
|
+
ToastAndroid,
|
|
10
|
+
StatusBar,
|
|
11
|
+
} from 'react-native';
|
|
12
|
+
import { useEffect, useRef, useState } from 'react';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
type WebViewProps,
|
|
16
|
+
type WebViewNavigation,
|
|
17
|
+
} from 'react-native-webview';
|
|
18
|
+
import {
|
|
19
|
+
WebViewCallback,
|
|
20
|
+
type WebViewCallbackFunction,
|
|
21
|
+
} from './utils/webviewCallback';
|
|
22
|
+
import {
|
|
23
|
+
check,
|
|
24
|
+
PERMISSIONS,
|
|
25
|
+
request,
|
|
26
|
+
RESULTS,
|
|
27
|
+
type Permission,
|
|
28
|
+
} from 'react-native-permissions';
|
|
29
|
+
import FileViewer from 'react-native-file-viewer';
|
|
30
|
+
import RNFS from 'react-native-fs';
|
|
31
|
+
import CookieManager from '@react-native-cookies/cookies';
|
|
32
|
+
import { AnalyticsLogger } from './analytics/analytics_logger';
|
|
33
|
+
|
|
34
|
+
interface ExtendedWebViewProps extends WebViewProps {
|
|
35
|
+
onPermissionRequest?: (event: any) => void;
|
|
36
|
+
androidPermissions?: {
|
|
37
|
+
camera?: boolean;
|
|
38
|
+
microphone?: boolean;
|
|
39
|
+
geolocation?: boolean;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
interface WebViewCustomProps {
|
|
43
|
+
url: string;
|
|
44
|
+
options?: Partial<ExtendedWebViewProps>;
|
|
45
|
+
onCallback?: WebViewCallbackFunction;
|
|
46
|
+
hostName?: string;
|
|
47
|
+
whitelistedUrls?: string[];
|
|
48
|
+
onPageFinished?: () => void;
|
|
49
|
+
}
|
|
50
|
+
const clearAllCookies = async () => {
|
|
51
|
+
try {
|
|
52
|
+
await CookieManager.clearAll(true);
|
|
53
|
+
console.log('clearing cookies');
|
|
54
|
+
} catch (e) {
|
|
55
|
+
console.error('Failed to clear cookies:', e);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const WebView = ({
|
|
60
|
+
url,
|
|
61
|
+
options,
|
|
62
|
+
onCallback,
|
|
63
|
+
hostName,
|
|
64
|
+
whitelistedUrls = [],
|
|
65
|
+
onPageFinished,
|
|
66
|
+
}: WebViewCustomProps) => {
|
|
67
|
+
const webviewRef = useRef<RNWebView | null>(null);
|
|
68
|
+
const [canGoBack, setCanGoBack] = useState(false);
|
|
69
|
+
const _analyticsLogger = new AnalyticsLogger();
|
|
70
|
+
// const [hasRedirected, setHasRedirected] = useState(false);
|
|
71
|
+
const [, setToast] = useState<{ visible: boolean; message: string } | null>(
|
|
72
|
+
null
|
|
73
|
+
);
|
|
74
|
+
const handleExternalUrl = async (url: string) => {
|
|
75
|
+
try {
|
|
76
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
77
|
+
await Linking.openURL(url);
|
|
78
|
+
// _analyticsLogger.logEvent({ event: 'REACT_NATIVE_OPEN_URL_EXTERNALLY' });
|
|
79
|
+
} catch (error) {
|
|
80
|
+
// Implement your toast here
|
|
81
|
+
if (Platform.OS === 'android') {
|
|
82
|
+
ToastAndroid.show(
|
|
83
|
+
'Oops! Something went wrong. Please try again.',
|
|
84
|
+
ToastAndroid.LONG
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
console.log('Application not found to open link');
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const showToast_with_code_message = (syntheticEvent: any) => {
|
|
91
|
+
const { nativeEvent } = syntheticEvent;
|
|
92
|
+
const errorCodesToHandle = [-2, -6, -8, -10];
|
|
93
|
+
if (errorCodesToHandle.includes(nativeEvent.code)) {
|
|
94
|
+
const message = `WebView Error: [${nativeEvent.code}] ${nativeEvent.description}`;
|
|
95
|
+
setToast({ visible: true, message });
|
|
96
|
+
|
|
97
|
+
if (nativeEvent.code === -2) {
|
|
98
|
+
if (Platform.OS === 'android') {
|
|
99
|
+
ToastAndroid.show(
|
|
100
|
+
'There seems to be a network issue. Please try again.',
|
|
101
|
+
ToastAndroid.LONG
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
clearAllCookies();
|
|
105
|
+
onCallback?.(WebViewCallback.redirect('WEBVIEW_ERROR'));
|
|
106
|
+
} else {
|
|
107
|
+
if (Platform.OS === 'android') {
|
|
108
|
+
ToastAndroid.show(
|
|
109
|
+
'Oops! Something went wrong. Please try again.',
|
|
110
|
+
ToastAndroid.LONG
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
clearAllCookies();
|
|
114
|
+
onCallback?.(WebViewCallback.redirect('WEBVIEW_ERROR'));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setTimeout(() => setToast(null), 6000);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const getQueryParam = (url: string, param: string): string | null => {
|
|
122
|
+
const match = url.match(new RegExp('[?&]' + param + '=([^&#]*)'));
|
|
123
|
+
return match && match[1] ? decodeURIComponent(match[1]) : null;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const downloadAndOpenFile = async (fileUrl: string) => {
|
|
127
|
+
try {
|
|
128
|
+
console.log('Starting file download...', fileUrl);
|
|
129
|
+
|
|
130
|
+
// Get cookies using CookieManager
|
|
131
|
+
let cookieString = '';
|
|
132
|
+
try {
|
|
133
|
+
const cookies = await CookieManager.get(fileUrl);
|
|
134
|
+
cookieString = Object.keys(cookies)
|
|
135
|
+
.map((key) => `${key}=${cookies[key]?.value ?? ''}`)
|
|
136
|
+
.join('; ');
|
|
137
|
+
} catch (e) {
|
|
138
|
+
console.error('Failed to get cookies:', e);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Create a clean filename from the URL
|
|
142
|
+
const timestamp = new Date().getTime();
|
|
143
|
+
// Extract only the last part of the path for the filename
|
|
144
|
+
const urlParts = fileUrl.split('/');
|
|
145
|
+
const lastPart = urlParts[urlParts.length - 1];
|
|
146
|
+
const fileExt = lastPart?.split('.').pop() || 'pdf';
|
|
147
|
+
const fileName = `${timestamp}.${fileExt}`;
|
|
148
|
+
|
|
149
|
+
const downloadPath = Platform.select({
|
|
150
|
+
ios: `${RNFS.DocumentDirectoryPath}/${fileName}`,
|
|
151
|
+
android: `${RNFS.DownloadDirectoryPath}/${fileName}`,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!downloadPath) {
|
|
155
|
+
throw new Error('Could not determine download path');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log('Downloading to:', downloadPath);
|
|
159
|
+
|
|
160
|
+
const options = {
|
|
161
|
+
fromUrl: fileUrl,
|
|
162
|
+
toFile: downloadPath,
|
|
163
|
+
headers: {
|
|
164
|
+
'Cookie': cookieString,
|
|
165
|
+
'Accept': 'application/pdf',
|
|
166
|
+
'Content-Type': 'application/pdf',
|
|
167
|
+
},
|
|
168
|
+
background: true,
|
|
169
|
+
begin: (res: any) => {
|
|
170
|
+
console.log('Download started with headers:', res);
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const response = await RNFS.downloadFile(options).promise;
|
|
175
|
+
|
|
176
|
+
if (response.statusCode === 200) {
|
|
177
|
+
console.log('File downloaded to:', downloadPath);
|
|
178
|
+
|
|
179
|
+
if (Platform.OS === 'android') {
|
|
180
|
+
ToastAndroid.show('File downloaded successfully', ToastAndroid.SHORT);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await FileViewer.open(downloadPath, {
|
|
184
|
+
showOpenWithDialog: true,
|
|
185
|
+
onDismiss: () => {
|
|
186
|
+
if (Platform.OS === 'ios') {
|
|
187
|
+
RNFS.unlink(downloadPath).catch(console.error);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
} else {
|
|
192
|
+
throw new Error(`Download failed with status ${response.statusCode}`);
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('File download/open error:', error);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const handleOnShouldStartLoadWithRequest = (event: WebViewNavigation) => {
|
|
200
|
+
const { url } = event;
|
|
201
|
+
console.log('URL:', url);
|
|
202
|
+
if (url === 'about:blank' || url === 'about:srcdoc') {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
// _analyticsLogger.logEvent({ event: 'REACT_NATIVE_LOADING_URL ', url });
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
url?.includes('/session-expired?status=') ||
|
|
209
|
+
url?.includes('/redirect?status=')
|
|
210
|
+
) {
|
|
211
|
+
console.log('overriding url');
|
|
212
|
+
const status = getQueryParam(url, 'status');
|
|
213
|
+
|
|
214
|
+
console.log('Status thrown from webview ', status);
|
|
215
|
+
// _analyticsLogger.logEvent({
|
|
216
|
+
// event: 'REACT_NATIVE_WEBVIEW_CALLBACK ',
|
|
217
|
+
// status,
|
|
218
|
+
// });
|
|
219
|
+
|
|
220
|
+
StatusBar.setBackgroundColor('#7E7E7EFF');
|
|
221
|
+
clearAllCookies();
|
|
222
|
+
onCallback?.(WebViewCallback.redirect(status ?? undefined));
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
if (url?.includes('/api/user/redirect')) {
|
|
226
|
+
console.log('overriding redirect url');
|
|
227
|
+
|
|
228
|
+
StatusBar.setBackgroundColor('#7E7E7EFF');
|
|
229
|
+
clearAllCookies();
|
|
230
|
+
onCallback?.(WebViewCallback.redirect('SESSION_EXPIRED'));
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Handle whitelisted URLs
|
|
235
|
+
const isWhitelisted =
|
|
236
|
+
whitelistedUrls.some((white) => url.includes(white)) ||
|
|
237
|
+
(hostName && url.includes(hostName));
|
|
238
|
+
|
|
239
|
+
if (
|
|
240
|
+
!isWhitelisted &&
|
|
241
|
+
url &&
|
|
242
|
+
url !== 'about:blank' &&
|
|
243
|
+
url !== 'about:srcdoc'
|
|
244
|
+
) {
|
|
245
|
+
console.log('External URL detected:', url);
|
|
246
|
+
handleExternalUrl(url);
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
if (
|
|
250
|
+
url.includes('.pdf') ||
|
|
251
|
+
url.includes('/statements/') ||
|
|
252
|
+
url.includes('/download_statements')
|
|
253
|
+
) {
|
|
254
|
+
console.log('File download URL detected:', url);
|
|
255
|
+
downloadAndOpenFile(url);
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return true;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const handleBackButton = () => {
|
|
263
|
+
if (canGoBack && webviewRef.current) {
|
|
264
|
+
webviewRef.current.goBack();
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
const backHandler = BackHandler.addEventListener(
|
|
272
|
+
'hardwareBackPress',
|
|
273
|
+
handleBackButton
|
|
274
|
+
);
|
|
275
|
+
return () => {
|
|
276
|
+
backHandler.remove();
|
|
277
|
+
};
|
|
278
|
+
}, [canGoBack]);
|
|
279
|
+
|
|
280
|
+
const Loading = () => (
|
|
281
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
282
|
+
<ActivityIndicator size="large" />
|
|
283
|
+
</View>
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
// Cookie injection script
|
|
287
|
+
|
|
288
|
+
const injectedJavaScript = `
|
|
289
|
+
window.onerror = function(message, source, lineno, colno, error) {
|
|
290
|
+
if (message.includes('RATE_LIMIT_USER')) {
|
|
291
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
292
|
+
type: 'RATE_LIMIT_ERROR'
|
|
293
|
+
}));
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
true;
|
|
297
|
+
`;
|
|
298
|
+
|
|
299
|
+
const requestPermission = async (permission: Permission) => {
|
|
300
|
+
try {
|
|
301
|
+
const result = await check(permission);
|
|
302
|
+
|
|
303
|
+
if (result === RESULTS.DENIED) {
|
|
304
|
+
const requestResult = await request(permission);
|
|
305
|
+
return requestResult === RESULTS.GRANTED;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return result === RESULTS.GRANTED;
|
|
309
|
+
} catch (error) {
|
|
310
|
+
console.error('Permission request failed:', error);
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const handlePermissionRequest = async (event: any) => {
|
|
316
|
+
const { resources } = event.nativeEvent;
|
|
317
|
+
console.log('Permission requested:', resources);
|
|
318
|
+
|
|
319
|
+
const permissionsToRequest: Permission[] = [];
|
|
320
|
+
|
|
321
|
+
if (resources.includes('video')) {
|
|
322
|
+
permissionsToRequest.push(
|
|
323
|
+
Platform.OS === 'ios'
|
|
324
|
+
? PERMISSIONS.IOS.CAMERA
|
|
325
|
+
: PERMISSIONS.ANDROID.CAMERA
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
if (resources.includes('microphone')) {
|
|
329
|
+
permissionsToRequest.push(
|
|
330
|
+
Platform.OS === 'ios'
|
|
331
|
+
? PERMISSIONS.IOS.MICROPHONE
|
|
332
|
+
: PERMISSIONS.ANDROID.RECORD_AUDIO
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
if (resources.includes('geolocation')) {
|
|
336
|
+
permissionsToRequest.push(
|
|
337
|
+
Platform.OS === 'ios'
|
|
338
|
+
? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
|
|
339
|
+
: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
const results = await Promise.all(
|
|
345
|
+
permissionsToRequest.map((permission) => requestPermission(permission))
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const granted = results.every((result) => result === true);
|
|
349
|
+
if (granted) {
|
|
350
|
+
// @ts-ignore - grant exists on the event
|
|
351
|
+
event.nativeEvent.grant();
|
|
352
|
+
} else {
|
|
353
|
+
// @ts-ignore - deny exists on the event
|
|
354
|
+
event.nativeEvent.deny();
|
|
355
|
+
}
|
|
356
|
+
} catch (error) {
|
|
357
|
+
console.error('Permission handling failed:', error);
|
|
358
|
+
// @ts-ignore - deny exists on the event
|
|
359
|
+
event.nativeEvent.deny();
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const handleWebViewLoadEnd = (syntheticEvent: any) => {
|
|
364
|
+
const loadedUrl = syntheticEvent?.nativeEvent?.url || url;
|
|
365
|
+
|
|
366
|
+
onPageFinished?.();
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
return (
|
|
370
|
+
<SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
|
|
371
|
+
<RNWebView
|
|
372
|
+
ref={webviewRef}
|
|
373
|
+
source={{ uri: url }}
|
|
374
|
+
onPermissionRequest={
|
|
375
|
+
handlePermissionRequest as ExtendedWebViewProps['onPermissionRequest']
|
|
376
|
+
}
|
|
377
|
+
geolocationEnabled={true}
|
|
378
|
+
androidPermissions={{
|
|
379
|
+
camera: true,
|
|
380
|
+
microphone: true,
|
|
381
|
+
geolocation: true,
|
|
382
|
+
}}
|
|
383
|
+
onError={(e) => {
|
|
384
|
+
showToast_with_code_message(e);
|
|
385
|
+
options?.onError?.(e as any);
|
|
386
|
+
}}
|
|
387
|
+
{...options}
|
|
388
|
+
startInLoadingState={true}
|
|
389
|
+
renderLoading={() => <Loading />}
|
|
390
|
+
onLoadEnd={handleWebViewLoadEnd}
|
|
391
|
+
originWhitelist={['*']}
|
|
392
|
+
javaScriptEnabled={true}
|
|
393
|
+
domStorageEnabled={true}
|
|
394
|
+
mediaPlaybackRequiresUserAction={false}
|
|
395
|
+
allowsInlineMediaPlayback={true}
|
|
396
|
+
onShouldStartLoadWithRequest={handleOnShouldStartLoadWithRequest}
|
|
397
|
+
onNavigationStateChange={(navState) => {
|
|
398
|
+
setCanGoBack(navState.canGoBack);
|
|
399
|
+
}}
|
|
400
|
+
injectedJavaScript={injectedJavaScript}
|
|
401
|
+
decelerationRate={Platform.OS === 'ios' ? 'normal' : 0.9}
|
|
402
|
+
allowsBackForwardNavigationGestures={Platform.OS === 'ios'}
|
|
403
|
+
sharedCookiesEnabled={true}
|
|
404
|
+
setSupportMultipleWindows={false}
|
|
405
|
+
mixedContentMode="always"
|
|
406
|
+
allowsLinkPreview={true}
|
|
407
|
+
/>
|
|
408
|
+
</SafeAreaView>
|
|
409
|
+
);
|
|
410
|
+
};
|
package/src/index.tsx
ADDED