@exodus/react-native-webview 11.26.1-exodus.7 → 11.26.1-exodus.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.
Files changed (119) hide show
  1. package/package.json +1 -1
  2. package/.all-contributorsrc +0 -185
  3. package/.circleci/config.yml +0 -66
  4. package/.eslintignore +0 -2
  5. package/.eslintrc.js +0 -94
  6. package/.flowconfig +0 -88
  7. package/.flowconfig.android +0 -88
  8. package/.gitattributes +0 -12
  9. package/.github/CODEOWNERS +0 -1
  10. package/.github/ISSUE_TEMPLATE/bug-report.md +0 -42
  11. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -30
  12. package/.github/workflows/android-ci.yml +0 -35
  13. package/.github/workflows/detox.yml +0 -20
  14. package/.github/workflows/ios-ci.yml +0 -31
  15. package/.github/workflows/scripts/install-vs-features.ps1 +0 -108
  16. package/.github/workflows/stale.yml +0 -17
  17. package/.gitignore +0 -62
  18. package/.prettierrc.js +0 -10
  19. package/.releaserc +0 -15
  20. package/.vscode/settings.json +0 -9
  21. package/android/.gradle/7.4.2/checksums/checksums.lock +0 -0
  22. package/android/.gradle/7.4.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  23. package/android/.gradle/7.4.2/dependencies-accessors/gc.properties +0 -0
  24. package/android/.gradle/7.4.2/executionHistory/executionHistory.lock +0 -0
  25. package/android/.gradle/7.4.2/fileChanges/last-build.bin +0 -0
  26. package/android/.gradle/7.4.2/fileHashes/fileHashes.lock +0 -0
  27. package/android/.gradle/7.4.2/gc.properties +0 -0
  28. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  29. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  30. package/android/.gradle/vcs-1/gc.properties +0 -0
  31. package/babel.config.js +0 -11
  32. package/bin/setup +0 -26
  33. package/docs/Contributing.md +0 -102
  34. package/docs/Custom-Android.md +0 -222
  35. package/docs/Custom-iOS.md +0 -236
  36. package/docs/Debugging.md +0 -101
  37. package/docs/Getting-Started.md +0 -142
  38. package/docs/Guide.md +0 -613
  39. package/docs/Reference.md +0 -1629
  40. package/example/.gitignore +0 -14
  41. package/example/.watchmanconfig +0 -1
  42. package/example/App.tsx +0 -262
  43. package/example/android/.gradle/7.3.3/checksums/checksums.lock +0 -0
  44. package/example/android/.gradle/7.3.3/checksums/md5-checksums.bin +0 -0
  45. package/example/android/.gradle/7.3.3/checksums/sha1-checksums.bin +0 -0
  46. package/example/android/.gradle/7.3.3/dependencies-accessors/dependencies-accessors.lock +0 -0
  47. package/example/android/.gradle/7.3.3/dependencies-accessors/gc.properties +0 -0
  48. package/example/android/.gradle/7.3.3/fileChanges/last-build.bin +0 -0
  49. package/example/android/.gradle/7.3.3/fileHashes/fileHashes.lock +0 -0
  50. package/example/android/.gradle/7.3.3/gc.properties +0 -0
  51. package/example/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  52. package/example/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  53. package/example/android/.gradle/vcs-1/gc.properties +0 -0
  54. package/example/android/build.gradle +0 -15
  55. package/example/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  56. package/example/android/gradle/wrapper/gradle-wrapper.properties +0 -5
  57. package/example/android/gradle.properties +0 -34
  58. package/example/android/gradlew +0 -234
  59. package/example/android/gradlew.bat +0 -89
  60. package/example/android/settings.gradle +0 -12
  61. package/example/app.json +0 -20
  62. package/example/assets/test.html +0 -9
  63. package/example/babel.config.js +0 -3
  64. package/example/examples/Alerts.tsx +0 -72
  65. package/example/examples/ApplePay.tsx +0 -23
  66. package/example/examples/Background.tsx +0 -54
  67. package/example/examples/Downloads.tsx +0 -57
  68. package/example/examples/Injection.tsx +0 -161
  69. package/example/examples/LocalPageLoad.tsx +0 -16
  70. package/example/examples/Messaging.tsx +0 -63
  71. package/example/examples/NativeWebpage.tsx +0 -22
  72. package/example/examples/Scrolling.tsx +0 -68
  73. package/example/examples/Uploads.tsx +0 -69
  74. package/example/index.js +0 -9
  75. package/example/ios/Podfile +0 -8
  76. package/example/ios/Podfile.lock +0 -445
  77. package/ios/Podfile +0 -10
  78. package/ios/Podfile.lock +0 -3
  79. package/ios/Pods/Manifest.lock +0 -3
  80. package/ios/Pods/Pods.xcodeproj/project.pbxproj +0 -397
  81. package/ios/Pods/Pods.xcodeproj/xcuserdata/gabrielezenwankwo.xcuserdatad/xcschemes/Pods-RNCWebView.xcscheme +0 -58
  82. package/ios/Pods/Pods.xcodeproj/xcuserdata/gabrielezenwankwo.xcuserdatad/xcschemes/xcschememanagement.plist +0 -16
  83. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView-Info.plist +0 -26
  84. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView-acknowledgements.markdown +0 -3
  85. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView-acknowledgements.plist +0 -29
  86. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView-dummy.m +0 -5
  87. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView-umbrella.h +0 -16
  88. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView.debug.xcconfig +0 -8
  89. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView.modulemap +0 -6
  90. package/ios/Pods/Target Support Files/Pods-RNCWebView/Pods-RNCWebView.release.xcconfig +0 -8
  91. package/ios/RNCWebView.xcworkspace/contents.xcworkspacedata +0 -32
  92. package/jest-setups/jest.setup.js +0 -8
  93. package/jest.config.js +0 -184
  94. package/lib/UpdateOS.d.ts +0 -6
  95. package/lib/UpdateOS.d.ts.map +0 -1
  96. package/lib/UpdateOS.js +0 -49
  97. package/lib/WebView.android.d.ts.map +0 -1
  98. package/lib/WebView.d.ts.map +0 -1
  99. package/lib/WebView.ios.d.ts.map +0 -1
  100. package/lib/WebView.styles.d.ts.map +0 -1
  101. package/lib/WebViewNativeComponent.android.d.ts.map +0 -1
  102. package/lib/WebViewNativeComponent.ios.d.ts.map +0 -1
  103. package/lib/WebViewShared.d.ts.map +0 -1
  104. package/lib/WebViewTypes.d.ts.map +0 -1
  105. package/lib/index.d.ts.map +0 -1
  106. package/metro.config.js +0 -57
  107. package/src/WebView.android.tsx +0 -246
  108. package/src/WebView.ios.tsx +0 -221
  109. package/src/WebView.styles.ts +0 -44
  110. package/src/WebView.tsx +0 -18
  111. package/src/WebViewNativeComponent.android.ts +0 -8
  112. package/src/WebViewNativeComponent.ios.ts +0 -8
  113. package/src/WebViewShared.tsx +0 -257
  114. package/src/WebViewTypes.ts +0 -914
  115. package/src/__tests__/WebViewShared-test.js +0 -208
  116. package/src/__tests__/__snapshots__/WebViewShared-test.js.snap +0 -8
  117. package/src/index.ts +0 -4
  118. package/tsconfig.json +0 -24
  119. package/yarn.lock +0 -13895
@@ -1,221 +0,0 @@
1
- import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
2
- import {
3
- Text,
4
- View,
5
- NativeModules,
6
- Platform,
7
- } from 'react-native';
8
- import invariant from 'invariant';
9
-
10
- // @ts-expect-error react-native doesn't have this type
11
- import codegenNativeCommandsUntyped from 'react-native/Libraries/Utilities/codegenNativeCommands';
12
- import RNCWebView from "./WebViewNativeComponent.ios";
13
- import {
14
- defaultOriginWhitelist,
15
- defaultRenderError,
16
- defaultRenderLoading,
17
- useWebWiewLogic,
18
- versionPasses,
19
- } from './WebViewShared';
20
- import {
21
- IOSWebViewProps,
22
- DecelerationRateConstant,
23
- NativeWebViewIOS,
24
- ViewManager,
25
- } from './WebViewTypes';
26
-
27
- import styles from './WebView.styles';
28
-
29
- const codegenNativeCommands = codegenNativeCommandsUntyped as <T extends {}>(options: { supportedCommands: (keyof T)[] }) => T;
30
-
31
- const Commands = codegenNativeCommands({
32
- supportedCommands: ['goBack', 'goForward', 'reload', 'stopLoading', /* 'injectJavaScript', */ 'requestFocus', 'postMessage', 'loadUrl'],
33
- });
34
-
35
- const processDecelerationRate = (
36
- decelerationRate: DecelerationRateConstant | number | undefined,
37
- ) => {
38
- let newDecelerationRate = decelerationRate;
39
- if (newDecelerationRate === 'normal') {
40
- newDecelerationRate = 0.998;
41
- } else if (newDecelerationRate === 'fast') {
42
- newDecelerationRate = 0.99;
43
- }
44
- return newDecelerationRate;
45
- };
46
-
47
- const RNCWebViewManager = NativeModules.RNCWebViewManager as ViewManager;
48
-
49
- const useWarnIfChanges = <T extends unknown>(value: T, name: string) => {
50
- const ref = useRef(value);
51
- if (ref.current !== value) {
52
- console.warn(`Changes to property ${name} do nothing after the initial render.`);
53
- ref.current = value;
54
- }
55
- }
56
-
57
- /**
58
- * Harcoded defaults for security.
59
- */
60
- const mediaPlaybackRequiresUserAction = true;
61
- // iOS only configs
62
- const allowsInlineMediaPlayback = true;
63
- const useSharedProcessPool = false;
64
- const sharedCookiesEnabled = false;
65
- const enableApplePay = false;
66
- const dataDetectorTypes = 'none';
67
- const hardMinimumIOSVersion = '12.5.6 <13, 13.6.1 <14, 14.8.1 <15, 15.7.1'
68
-
69
- const WebViewComponent = forwardRef<{}, IOSWebViewProps>(({
70
- javaScriptEnabled = true,
71
- cacheEnabled = true,
72
- originWhitelist = defaultOriginWhitelist,
73
- textInteractionEnabled= true,
74
- injectedJavaScript,
75
- injectedJavaScriptBeforeContentLoaded,
76
- startInLoadingState,
77
- onLoadStart,
78
- onError,
79
- onLoad,
80
- onLoadEnd,
81
- onMessage: onMessageProp,
82
- renderLoading,
83
- renderError,
84
- style,
85
- containerStyle,
86
- source,
87
- incognito,
88
- validateMeta,
89
- validateData,
90
- decelerationRate: decelerationRateProp,
91
- onShouldStartLoadWithRequest: onShouldStartLoadWithRequestProp,
92
- minimumIOSVersion,
93
- unsupportedVersionComponent: UnsupportedVersionComponent,
94
- ...otherProps
95
- }, ref) => {
96
- const webViewRef = useRef<NativeWebViewIOS | null>(null);
97
-
98
- const onShouldStartLoadWithRequestCallback = useCallback((
99
- shouldStart: boolean,
100
- _url: string,
101
- lockIdentifier = 0,
102
- ) => {
103
- const viewManager = RNCWebViewManager;
104
-
105
- viewManager.startLoadWithResult(!!shouldStart, lockIdentifier);
106
- }, []);
107
-
108
- const { onLoadingStart, onShouldStartLoadWithRequest, onMessage, viewState, setViewState, lastErrorEvent, onLoadingError, onLoadingFinish, onLoadingProgress } = useWebWiewLogic({
109
- onLoad,
110
- onError,
111
- onLoadEnd,
112
- onLoadStart,
113
- onMessageProp,
114
- startInLoadingState,
115
- originWhitelist,
116
- onShouldStartLoadWithRequestProp,
117
- onShouldStartLoadWithRequestCallback,
118
- validateMeta,
119
- validateData,
120
- });
121
-
122
- useImperativeHandle(ref, () => ({
123
- goForward: () => Commands.goForward(webViewRef.current),
124
- goBack: () => Commands.goBack(webViewRef.current),
125
- reload: () => {
126
- setViewState(
127
- 'LOADING',
128
- ); Commands.reload(webViewRef.current)
129
- },
130
- stopLoading: () => Commands.stopLoading(webViewRef.current),
131
- postMessage: (data: string) => Commands.postMessage(webViewRef.current, data),
132
- // injectJavaScript: (data: string) => Commands.injectJavaScript(webViewRef.current, data),
133
- requestFocus: () => Commands.requestFocus(webViewRef.current),
134
- }), [setViewState, webViewRef]);
135
-
136
-
137
- useWarnIfChanges(allowsInlineMediaPlayback, 'allowsInlineMediaPlayback');
138
- useWarnIfChanges(incognito, 'incognito');
139
- useWarnIfChanges(mediaPlaybackRequiresUserAction, 'mediaPlaybackRequiresUserAction');
140
- useWarnIfChanges(dataDetectorTypes, 'dataDetectorTypes');
141
-
142
- const version = String(Platform.Version)
143
- if (!(versionPasses(version, minimumIOSVersion) && versionPasses(version, hardMinimumIOSVersion))) {
144
- if (UnsupportedVersionComponent) {
145
- return <UnsupportedVersionComponent />
146
- }
147
- return (
148
- <View style={{ alignSelf: 'flex-start' }}>
149
- <Text style={{ color: 'red' }}>
150
- iOS version is outdated and insecure. Update it to continue.
151
- </Text>
152
- </View>
153
- );
154
- }
155
-
156
- let otherView = null;
157
- if (viewState === 'LOADING') {
158
- otherView = (renderLoading || defaultRenderLoading)();
159
- } else if (viewState === 'ERROR') {
160
- invariant(lastErrorEvent != null, 'lastErrorEvent expected to be non-null');
161
- otherView = (renderError || defaultRenderError)(
162
- lastErrorEvent.domain,
163
- lastErrorEvent.code,
164
- lastErrorEvent.description,
165
- );
166
- } else if (viewState !== 'IDLE') {
167
- console.error(`RNCWebView invalid state encountered: ${viewState}`);
168
- }
169
-
170
- const webViewStyles = [styles.container, styles.webView, style];
171
- const webViewContainerStyle = [styles.container, containerStyle];
172
-
173
- const decelerationRate = processDecelerationRate(decelerationRateProp);
174
-
175
- const NativeWebView = RNCWebView;
176
-
177
- const webView = (
178
- <NativeWebView
179
- key="webViewKey"
180
- {...otherProps}
181
- enableApplePay={enableApplePay}
182
- javaScriptEnabled={javaScriptEnabled}
183
- cacheEnabled={cacheEnabled}
184
- dataDetectorTypes={dataDetectorTypes}
185
- useSharedProcessPool={useSharedProcessPool}
186
- textInteractionEnabled={textInteractionEnabled}
187
- decelerationRate={decelerationRate}
188
- messagingEnabled={typeof onMessageProp === 'function'}
189
- onLoadingError={onLoadingError}
190
- onLoadingFinish={onLoadingFinish}
191
- onLoadingProgress={onLoadingProgress}
192
- onLoadingStart={onLoadingStart}
193
- onMessage={onMessage}
194
- onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
195
- injectedJavaScript={injectedJavaScript}
196
- injectedJavaScriptBeforeContentLoaded={injectedJavaScriptBeforeContentLoaded}
197
- allowsInlineMediaPlayback={allowsInlineMediaPlayback}
198
- incognito={incognito}
199
- mediaPlaybackRequiresUserAction={mediaPlaybackRequiresUserAction}
200
- ref={webViewRef}
201
- sharedCookiesEnabled={sharedCookiesEnabled}
202
- // TODO: find a better way to type this.
203
- source={source}
204
- style={webViewStyles}
205
- />
206
- );
207
-
208
- return (
209
- <View style={webViewContainerStyle}>
210
- {webView}
211
- {otherView}
212
- </View>
213
- );})
214
-
215
- // no native implementation for iOS, depends only on permissions
216
- const isFileUploadSupported: () => Promise<boolean>
217
- = async () => true;
218
-
219
- const WebView = Object.assign(WebViewComponent, {isFileUploadSupported});
220
-
221
- export default WebView;
@@ -1,44 +0,0 @@
1
- import { StyleSheet, ViewStyle, TextStyle } from 'react-native';
2
-
3
- interface Styles {
4
- container: ViewStyle;
5
- errorText: TextStyle;
6
- errorTextTitle: TextStyle;
7
- loadingOrErrorView: ViewStyle;
8
- webView: ViewStyle;
9
- loadingProgressBar: ViewStyle;
10
- }
11
-
12
- const styles = StyleSheet.create<Styles>({
13
- container: {
14
- flex: 1,
15
- overflow: 'hidden',
16
- },
17
- loadingOrErrorView: {
18
- position: 'absolute',
19
- flex: 1,
20
- justifyContent: 'center',
21
- alignItems: 'center',
22
- height: '100%',
23
- width: '100%',
24
- backgroundColor: 'white'
25
- },
26
- loadingProgressBar: {
27
- height: 20,
28
- },
29
- errorText: {
30
- fontSize: 14,
31
- textAlign: 'center',
32
- marginBottom: 2,
33
- },
34
- errorTextTitle: {
35
- fontSize: 15,
36
- fontWeight: '500',
37
- marginBottom: 10,
38
- },
39
- webView: {
40
- backgroundColor: '#ffffff',
41
- },
42
- });
43
-
44
- export default styles;
package/src/WebView.tsx DELETED
@@ -1,18 +0,0 @@
1
- import React from 'react';
2
- import { Text, View } from 'react-native';
3
- import { IOSWebViewProps, AndroidWebViewProps } from './WebViewTypes';
4
-
5
- export type WebViewProps = IOSWebViewProps & AndroidWebViewProps;
6
-
7
- // This "dummy" WebView is to render something for unsupported platforms,
8
- // like for example Expo SDK "web" platform.
9
- const WebView: React.FunctionComponent<WebViewProps> = () => (
10
- <View style={{ alignSelf: 'flex-start' }}>
11
- <Text style={{ color: 'red' }}>
12
- React Native WebView does not support this platform.
13
- </Text>
14
- </View>
15
- );
16
-
17
- export { WebView };
18
- export default WebView;
@@ -1,8 +0,0 @@
1
- import { requireNativeComponent } from "react-native";
2
- import type { NativeWebViewAndroid } from "./WebViewTypes";
3
-
4
- const RNCWebView: typeof NativeWebViewAndroid = requireNativeComponent(
5
- 'RNCWebView',
6
- );
7
-
8
- export default RNCWebView;
@@ -1,8 +0,0 @@
1
- import { requireNativeComponent } from "react-native";
2
- import type { NativeWebViewIOS } from "./WebViewTypes";
3
-
4
- const RNCWebView: typeof NativeWebViewIOS = requireNativeComponent(
5
- 'RNCWebView',
6
- );
7
-
8
- export default RNCWebView;
@@ -1,257 +0,0 @@
1
- import escapeStringRegexp from 'escape-string-regexp';
2
- import React, { useCallback, useMemo, useRef, useState } from 'react';
3
- import { Linking, View, ActivityIndicator, Text, Platform } from 'react-native';
4
- import {
5
- OnShouldStartLoadWithRequest,
6
- ShouldStartLoadRequestEvent,
7
- WebViewError,
8
- WebViewErrorEvent,
9
- WebViewMessageEvent,
10
- WebViewMessage,
11
- WebViewNavigationEvent,
12
- WebViewProgressEvent,
13
- WebViewNativeEvent,
14
- } from './WebViewTypes';
15
- import styles from './WebView.styles';
16
-
17
- const defaultOriginWhitelist = ['https://*'] as const;
18
-
19
- const extractOrigin = (url: string): string => {
20
- const result = /^[A-Za-z][A-Za-z0-9+\-.]+:(\/\/)?[^/]*/.exec(url);
21
- return result === null ? '' : result[0];
22
- };
23
-
24
- const originWhitelistToRegex = (originWhitelist: string): string =>
25
- `^${escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*')}$`;
26
-
27
- const _passesWhitelist = (
28
- compiledWhitelist: readonly string[],
29
- url: string,
30
- ) => {
31
- const origin = extractOrigin(url);
32
- if (!origin) return false;
33
- if (origin !== new URL(url).origin) return null;
34
- return compiledWhitelist.some(x => new RegExp(x).test(origin));
35
- };
36
-
37
- const compileWhitelist = (
38
- originWhitelist: readonly string[],
39
- ): readonly string[] =>
40
- ['about:blank', ...(originWhitelist || [])].map(originWhitelistToRegex);
41
-
42
- const createOnShouldStartLoadWithRequest = (
43
- loadRequest: (
44
- shouldStart: boolean,
45
- url: string,
46
- lockIdentifier: number,
47
- ) => void,
48
- originWhitelist: readonly string[],
49
- onShouldStartLoadWithRequest?: OnShouldStartLoadWithRequest,
50
- ) => {
51
- return ({ nativeEvent }: ShouldStartLoadRequestEvent) => {
52
- let shouldStart = true;
53
- const { url, lockIdentifier } = nativeEvent;
54
-
55
- if (!_passesWhitelist(compileWhitelist(originWhitelist), url)) {
56
- Linking.canOpenURL(url).then((supported) => {
57
- if (supported && /^https:\/\//.test(url)) {
58
- return Linking.openURL(url);
59
- }
60
- console.warn(`Can't open url: ${url}`);
61
- return undefined;
62
- }).catch(e => {
63
- console.warn('Error opening URL: ', e);
64
- });
65
- shouldStart = false;
66
- } else if (onShouldStartLoadWithRequest) {
67
- shouldStart = onShouldStartLoadWithRequest(nativeEvent);
68
- }
69
-
70
- loadRequest(shouldStart, url, lockIdentifier);
71
- };
72
- };
73
-
74
- const defaultRenderLoading = () => (
75
- <View style={styles.loadingOrErrorView}>
76
- <ActivityIndicator />
77
- </View>
78
- );
79
- const defaultRenderError = (
80
- errorDomain: string | undefined,
81
- errorCode: number,
82
- errorDesc: string,
83
- ) => (
84
- <View style={styles.loadingOrErrorView}>
85
- <Text style={styles.errorTextTitle}>Error loading page</Text>
86
- <Text style={styles.errorText}>{`Domain: ${errorDomain}`}</Text>
87
- <Text style={styles.errorText}>{`Error Code: ${errorCode}`}</Text>
88
- <Text style={styles.errorText}>{`Description: ${errorDesc}`}</Text>
89
- </View>
90
- );
91
-
92
- export {
93
- defaultOriginWhitelist,
94
- createOnShouldStartLoadWithRequest,
95
- defaultRenderLoading,
96
- defaultRenderError,
97
- };
98
-
99
-
100
- export const useWebWiewLogic = ({
101
- startInLoadingState,
102
- onLoadStart,
103
- onLoad,
104
- onLoadEnd,
105
- onError,
106
- onMessageProp,
107
- originWhitelist,
108
- onShouldStartLoadWithRequestProp,
109
- onShouldStartLoadWithRequestCallback,
110
- validateMeta,
111
- validateData,
112
- }: {
113
- startInLoadingState?: boolean
114
- onLoadStart?: (event: WebViewNavigationEvent) => void;
115
- onLoad?: (event: WebViewNavigationEvent) => void;
116
- onLoadEnd?: (event: WebViewNavigationEvent | WebViewErrorEvent) => void;
117
- onError?: (event: WebViewErrorEvent) => void;
118
- onMessageProp?: (event: WebViewMessage) => void;
119
- originWhitelist: readonly string[];
120
- onShouldStartLoadWithRequestProp?: OnShouldStartLoadWithRequest;
121
- onShouldStartLoadWithRequestCallback: (shouldStart: boolean, url: string, lockIdentifier?: number | undefined) => void;
122
- validateMeta: (event: WebViewNativeEvent) => WebViewNativeEvent;
123
- validateData: (data: object) => object;
124
- }) => {
125
-
126
- const [viewState, setViewState] = useState<'IDLE' | 'LOADING' | 'ERROR'>(startInLoadingState ? "LOADING" : "IDLE");
127
- const [lastErrorEvent, setLastErrorEvent] = useState<WebViewError | null>(null);
128
- const startUrl = useRef<string | null>(null)
129
-
130
- const passesWhitelist = (url: string) => {
131
- if (!url || typeof url !== 'string') return false;
132
- return _passesWhitelist(compileWhitelist(originWhitelist), url);
133
- }
134
-
135
- const passesWhitelistUse = useCallback(passesWhitelist, [originWhitelist])
136
-
137
- const extractMeta = (nativeEvent: WebViewNativeEvent): WebViewNativeEvent => ({
138
- url: String(nativeEvent.url),
139
- loading: Boolean(nativeEvent.loading),
140
- title: String(nativeEvent.title),
141
- canGoBack: Boolean(nativeEvent.canGoBack),
142
- canGoForward: Boolean(nativeEvent.canGoForward),
143
- lockIdentifier: Number(nativeEvent.lockIdentifier),
144
- });
145
-
146
- const onLoadingStart = useCallback((event: WebViewNavigationEvent) => {
147
- // Needed for android
148
- startUrl.current = event.nativeEvent.url;
149
- // !Needed for android
150
-
151
- onLoadStart?.(event);
152
- }, [onLoadStart]);
153
-
154
- const onLoadingError = useCallback((event: WebViewErrorEvent) => {
155
- event.persist();
156
- if (onError) {
157
- onError(event);
158
- } else {
159
- console.warn('Encountered an error loading page', event.nativeEvent);
160
- }
161
- onLoadEnd?.(event);
162
- if (event.isDefaultPrevented()) { return };
163
- setViewState('ERROR');
164
- setLastErrorEvent(event.nativeEvent);
165
- }, [onError, onLoadEnd]);
166
-
167
- const onLoadingFinish = useCallback((event: WebViewNavigationEvent) => {
168
- onLoad?.(event);
169
- onLoadEnd?.(event);
170
- const { nativeEvent: { url } } = event;
171
- if (!passesWhitelistUse(url)) return;
172
-
173
- // on Android, only if url === startUrl
174
- if (Platform.OS !== "android" || url === startUrl.current) {
175
- setViewState('IDLE');
176
- }
177
- // !on Android, only if url === startUrl
178
- // REMOVED: updateNavigationState(event);
179
- }, [onLoad, onLoadEnd, passesWhitelistUse]);
180
-
181
- const onMessage = useCallback((event: WebViewMessageEvent) => {
182
- const { nativeEvent } = event;
183
- if (!passesWhitelistUse(nativeEvent.url)) return;
184
-
185
- // TODO: can/should we perform any other validation?
186
-
187
- const data = JSON.stringify(validateData(JSON.parse(nativeEvent.data)));
188
- const meta = validateMeta(extractMeta(nativeEvent));
189
-
190
- onMessageProp?.({ ...meta, data });
191
- }, [onMessageProp, passesWhitelistUse, validateData, validateMeta]);
192
-
193
- const onLoadingProgress = useCallback((event: WebViewProgressEvent) => {
194
- const { nativeEvent: { progress } } = event;
195
- if (!passesWhitelistUse(event.nativeEvent.url)) return;
196
-
197
- // patch for Android only
198
- if (Platform.OS === "android" && progress === 1) {
199
- setViewState(prevViewState => prevViewState === 'LOADING' ? 'IDLE' : prevViewState);
200
- }
201
- // !patch for Android only
202
- // REMOVED: onLoadProgress?.(event);
203
- }, [passesWhitelistUse]);
204
-
205
- const onShouldStartLoadWithRequest = useMemo(() => createOnShouldStartLoadWithRequest(
206
- onShouldStartLoadWithRequestCallback,
207
- originWhitelist,
208
- onShouldStartLoadWithRequestProp,
209
- )
210
- , [originWhitelist, onShouldStartLoadWithRequestProp, onShouldStartLoadWithRequestCallback])
211
-
212
- return {
213
- onShouldStartLoadWithRequest,
214
- onLoadingStart,
215
- onLoadingProgress,
216
- onLoadingError,
217
- onLoadingFinish,
218
- onMessage,
219
- passesWhitelist,
220
- viewState,
221
- setViewState,
222
- lastErrorEvent,
223
- }
224
- };
225
-
226
- export const versionPasses = (version: string | undefined, minimum: string | undefined): boolean => {
227
- if (!version || !minimum) return false
228
- if (typeof version !== 'string' || typeof minimum !== 'string') return false
229
-
230
- if (minimum.includes(', ')) {
231
- // We have a set of possible versions
232
- const variants = minimum.split(', ')
233
- // Every entry but the last one should be with an upper bound
234
- if (!variants.slice(0, -1).every(x => x.includes(' <'))) return false
235
- return variants.some(x => versionPasses(version, x)) // Any match passes
236
- }
237
-
238
- if (minimum.includes(' <')) {
239
- const [min, max, ...rest] = minimum.split(' <')
240
- if (rest.length > 0) return false
241
- // Last check is required for correctness/formatting validation
242
- return versionPasses(version, min) && !versionPasses(version, max) && versionPasses(max, version)
243
- }
244
-
245
- const versionRegex = /^[0-9]+(\.[0-9]+)*$/
246
- if (!versionRegex.test(version) || !versionRegex.test(minimum)) return false
247
- const versionParts = version.split('.').map(Number)
248
- const minimumParts = minimum.split('.').map(Number)
249
- const len = Math.max(versionParts.length, minimumParts.length)
250
- for (let i = 0; i < len; i += 1) {
251
- const ver = versionParts[i] || 0
252
- const min = minimumParts[i] || 0
253
- if (ver > min) return true
254
- if (ver < min) return false
255
- }
256
- return true // equals
257
- }