@exodus/react-native-webview 9.4.0-no-android.0 → 11.26.1-exodus.1
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/README.md +21 -18
- package/android/.editorconfig +6 -0
- package/android/build.gradle +137 -0
- package/android/gradle.properties +6 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewFileProvider.java +14 -0
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java +1650 -0
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java +550 -0
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.kt +15 -0
- package/android/src/main/java/com/reactnativecommunity/webview/WebViewConfig.java +12 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopHttpErrorEvent.kt +25 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingErrorEvent.kt +25 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingFinishEvent.kt +24 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingProgressEvent.kt +24 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingStartEvent.kt +25 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopMessageEvent.kt +24 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopRenderProcessGoneEvent.kt +26 -0
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopShouldStartLoadWithRequestEvent.kt +29 -0
- package/android/src/main/res/xml/file_provider_paths.xml +6 -0
- package/apple/RNCWKProcessPoolManager.h +15 -0
- package/apple/RNCWKProcessPoolManager.m +36 -0
- package/apple/RNCWebView.h +117 -0
- package/apple/RNCWebView.m +1532 -0
- package/apple/RNCWebViewManager.h +13 -0
- package/apple/RNCWebViewManager.m +288 -0
- package/index.d.ts +65 -0
- package/index.js +4 -0
- package/ios/RNCWebView.xcodeproj/project.pbxproj +2 -0
- package/lib/WebView.android.d.ts +7 -0
- package/lib/WebView.android.js +125 -1
- package/lib/WebView.d.ts +7 -0
- package/lib/WebView.ios.d.ts +7 -0
- package/lib/WebView.ios.js +148 -202
- package/lib/WebView.js +9 -2
- package/lib/WebView.styles.d.ts +12 -0
- package/lib/WebView.styles.js +7 -7
- package/lib/WebViewNativeComponent.android.d.ts +4 -0
- package/lib/WebViewNativeComponent.android.js +3 -0
- package/lib/WebViewNativeComponent.ios.d.ts +4 -0
- package/lib/WebViewNativeComponent.ios.js +3 -0
- package/lib/WebViewShared.d.ts +37 -0
- package/lib/WebViewShared.js +121 -24
- package/lib/WebViewTypes.d.ts +873 -0
- package/lib/WebViewTypes.js +31 -16
- package/lib/index.d.ts +4 -0
- package/lib/index.js +3 -0
- package/package.json +83 -87
- package/react-native-webview.podspec +4 -4
- package/react-native.config.js +37 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#import <React/RCTViewManager.h>
|
|
9
|
+
|
|
10
|
+
@interface RNCWebViewManager : RCTViewManager
|
|
11
|
+
@property (nonatomic, copy) NSArray<NSDictionary *> * _Nullable menuItems;
|
|
12
|
+
@property (nonatomic, copy) RCTDirectEventBlock onCustomMenuSelection;
|
|
13
|
+
@end
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#import "RNCWebViewManager.h"
|
|
9
|
+
|
|
10
|
+
#import <React/RCTUIManager.h>
|
|
11
|
+
#import <React/RCTDefines.h>
|
|
12
|
+
#import "RNCWebView.h"
|
|
13
|
+
|
|
14
|
+
@interface RNCWebViewManager () <RNCWebViewDelegate>
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
@implementation RCTConvert (WKWebView)
|
|
18
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* iOS 13 */
|
|
19
|
+
RCT_ENUM_CONVERTER(WKContentMode, (@{
|
|
20
|
+
@"recommended": @(WKContentModeRecommended),
|
|
21
|
+
@"mobile": @(WKContentModeMobile),
|
|
22
|
+
@"desktop": @(WKContentModeDesktop),
|
|
23
|
+
}), WKContentModeRecommended, integerValue)
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 150000 /* iOS 15 */
|
|
27
|
+
RCT_ENUM_CONVERTER(RNCWebViewPermissionGrantType, (@{
|
|
28
|
+
@"grantIfSameHostElsePrompt": @(RNCWebViewPermissionGrantType_GrantIfSameHost_ElsePrompt),
|
|
29
|
+
@"grantIfSameHostElseDeny": @(RNCWebViewPermissionGrantType_GrantIfSameHost_ElseDeny),
|
|
30
|
+
@"deny": @(RNCWebViewPermissionGrantType_Deny),
|
|
31
|
+
@"grant": @(RNCWebViewPermissionGrantType_Grant),
|
|
32
|
+
@"prompt": @(RNCWebViewPermissionGrantType_Prompt),
|
|
33
|
+
}), RNCWebViewPermissionGrantType_Prompt, integerValue)
|
|
34
|
+
#endif
|
|
35
|
+
@end
|
|
36
|
+
|
|
37
|
+
@implementation RNCWebViewManager
|
|
38
|
+
{
|
|
39
|
+
NSConditionLock *_shouldStartLoadLock;
|
|
40
|
+
BOOL _shouldStartLoad;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
RCT_EXPORT_MODULE()
|
|
44
|
+
|
|
45
|
+
#if !TARGET_OS_OSX
|
|
46
|
+
- (UIView *)view
|
|
47
|
+
#else
|
|
48
|
+
- (RCTUIView *)view
|
|
49
|
+
#endif // !TARGET_OS_OSX
|
|
50
|
+
{
|
|
51
|
+
RNCWebView *webView = [RNCWebView new];
|
|
52
|
+
webView.delegate = self;
|
|
53
|
+
return webView;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary)
|
|
57
|
+
RCT_EXPORT_VIEW_PROPERTY(onFileDownload, RCTDirectEventBlock)
|
|
58
|
+
RCT_EXPORT_VIEW_PROPERTY(onLoadingStart, RCTDirectEventBlock)
|
|
59
|
+
RCT_EXPORT_VIEW_PROPERTY(onLoadingFinish, RCTDirectEventBlock)
|
|
60
|
+
RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock)
|
|
61
|
+
RCT_EXPORT_VIEW_PROPERTY(onLoadingProgress, RCTDirectEventBlock)
|
|
62
|
+
RCT_EXPORT_VIEW_PROPERTY(onHttpError, RCTDirectEventBlock)
|
|
63
|
+
RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock)
|
|
64
|
+
RCT_EXPORT_VIEW_PROPERTY(onContentProcessDidTerminate, RCTDirectEventBlock)
|
|
65
|
+
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString)
|
|
66
|
+
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptBeforeContentLoaded, NSString)
|
|
67
|
+
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptForMainFrameOnly, BOOL)
|
|
68
|
+
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptBeforeContentLoadedForMainFrameOnly, BOOL)
|
|
69
|
+
RCT_EXPORT_VIEW_PROPERTY(javaScriptEnabled, BOOL)
|
|
70
|
+
RCT_EXPORT_VIEW_PROPERTY(allowFileAccessFromFileURLs, BOOL)
|
|
71
|
+
RCT_EXPORT_VIEW_PROPERTY(allowUniversalAccessFromFileURLs, BOOL)
|
|
72
|
+
RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL)
|
|
73
|
+
RCT_EXPORT_VIEW_PROPERTY(allowsAirPlayForMediaPlayback, BOOL)
|
|
74
|
+
RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL)
|
|
75
|
+
#if WEBKIT_IOS_10_APIS_AVAILABLE
|
|
76
|
+
RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes)
|
|
77
|
+
#endif
|
|
78
|
+
RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets)
|
|
79
|
+
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL)
|
|
80
|
+
RCT_EXPORT_VIEW_PROPERTY(autoManageStatusBarEnabled, BOOL)
|
|
81
|
+
RCT_EXPORT_VIEW_PROPERTY(hideKeyboardAccessoryView, BOOL)
|
|
82
|
+
RCT_EXPORT_VIEW_PROPERTY(allowsBackForwardNavigationGestures, BOOL)
|
|
83
|
+
RCT_EXPORT_VIEW_PROPERTY(incognito, BOOL)
|
|
84
|
+
RCT_EXPORT_VIEW_PROPERTY(pagingEnabled, BOOL)
|
|
85
|
+
RCT_EXPORT_VIEW_PROPERTY(applicationNameForUserAgent, NSString)
|
|
86
|
+
RCT_EXPORT_VIEW_PROPERTY(cacheEnabled, BOOL)
|
|
87
|
+
RCT_EXPORT_VIEW_PROPERTY(allowsLinkPreview, BOOL)
|
|
88
|
+
RCT_EXPORT_VIEW_PROPERTY(allowingReadAccessToURL, NSString)
|
|
89
|
+
RCT_EXPORT_VIEW_PROPERTY(basicAuthCredential, NSDictionary)
|
|
90
|
+
|
|
91
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
|
92
|
+
RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior)
|
|
93
|
+
#endif
|
|
94
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */
|
|
95
|
+
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustsScrollIndicatorInsets, BOOL)
|
|
96
|
+
#endif
|
|
97
|
+
|
|
98
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* iOS 13 */
|
|
99
|
+
RCT_EXPORT_VIEW_PROPERTY(contentMode, WKContentMode)
|
|
100
|
+
#endif
|
|
101
|
+
|
|
102
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000 /* iOS 14 */
|
|
103
|
+
RCT_EXPORT_VIEW_PROPERTY(limitsNavigationsToAppBoundDomains, BOOL)
|
|
104
|
+
#endif
|
|
105
|
+
|
|
106
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500 /* iOS 14.5 */
|
|
107
|
+
RCT_EXPORT_VIEW_PROPERTY(textInteractionEnabled, BOOL)
|
|
108
|
+
#endif
|
|
109
|
+
|
|
110
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 150000 /* iOS 15 */
|
|
111
|
+
RCT_EXPORT_VIEW_PROPERTY(mediaCapturePermissionGrantType, RNCWebViewPermissionGrantType)
|
|
112
|
+
#endif
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Expose methods to enable messaging the webview.
|
|
116
|
+
*/
|
|
117
|
+
RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL)
|
|
118
|
+
RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock)
|
|
119
|
+
RCT_EXPORT_VIEW_PROPERTY(onScroll, RCTDirectEventBlock)
|
|
120
|
+
RCT_EXPORT_VIEW_PROPERTY(enableApplePay, BOOL)
|
|
121
|
+
RCT_EXPORT_VIEW_PROPERTY(menuItems, NSArray);
|
|
122
|
+
RCT_EXPORT_VIEW_PROPERTY(onCustomMenuSelection, RCTDirectEventBlock)
|
|
123
|
+
|
|
124
|
+
RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message)
|
|
125
|
+
{
|
|
126
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
127
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
128
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
129
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
130
|
+
} else {
|
|
131
|
+
[view postMessage:message];
|
|
132
|
+
}
|
|
133
|
+
}];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
RCT_CUSTOM_VIEW_PROPERTY(pullToRefreshEnabled, BOOL, RNCWebView) {
|
|
137
|
+
view.pullToRefreshEnabled = json == nil ? false : [RCTConvert BOOL: json];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
RCT_CUSTOM_VIEW_PROPERTY(bounces, BOOL, RNCWebView) {
|
|
141
|
+
view.bounces = json == nil ? true : [RCTConvert BOOL: json];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
RCT_CUSTOM_VIEW_PROPERTY(useSharedProcessPool, BOOL, RNCWebView) {
|
|
145
|
+
view.useSharedProcessPool = json == nil ? true : [RCTConvert BOOL: json];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
RCT_CUSTOM_VIEW_PROPERTY(userAgent, NSString, RNCWebView) {
|
|
149
|
+
view.userAgent = [RCTConvert NSString: json];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, RNCWebView) {
|
|
153
|
+
view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
RCT_CUSTOM_VIEW_PROPERTY(sharedCookiesEnabled, BOOL, RNCWebView) {
|
|
157
|
+
view.sharedCookiesEnabled = json == nil ? false : [RCTConvert BOOL: json];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#if !TARGET_OS_OSX
|
|
161
|
+
RCT_CUSTOM_VIEW_PROPERTY(decelerationRate, CGFloat, RNCWebView) {
|
|
162
|
+
view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json];
|
|
163
|
+
}
|
|
164
|
+
#endif // !TARGET_OS_OSX
|
|
165
|
+
|
|
166
|
+
RCT_CUSTOM_VIEW_PROPERTY(directionalLockEnabled, BOOL, RNCWebView) {
|
|
167
|
+
view.directionalLockEnabled = json == nil ? true : [RCTConvert BOOL: json];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
RCT_CUSTOM_VIEW_PROPERTY(showsHorizontalScrollIndicator, BOOL, RNCWebView) {
|
|
171
|
+
view.showsHorizontalScrollIndicator = json == nil ? true : [RCTConvert BOOL: json];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
RCT_CUSTOM_VIEW_PROPERTY(showsVerticalScrollIndicator, BOOL, RNCWebView) {
|
|
175
|
+
view.showsVerticalScrollIndicator = json == nil ? true : [RCTConvert BOOL: json];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
RCT_CUSTOM_VIEW_PROPERTY(keyboardDisplayRequiresUserAction, BOOL, RNCWebView) {
|
|
179
|
+
view.keyboardDisplayRequiresUserAction = json == nil ? true : [RCTConvert BOOL: json];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
RCT_EXPORT_METHOD(injectJavaScript:(nonnull NSNumber *)reactTag script:(NSString *)script)
|
|
183
|
+
{
|
|
184
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
185
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
186
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
187
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
188
|
+
} else {
|
|
189
|
+
[view injectJavaScript:script];
|
|
190
|
+
}
|
|
191
|
+
}];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
RCT_EXPORT_METHOD(goBack:(nonnull NSNumber *)reactTag)
|
|
195
|
+
{
|
|
196
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
197
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
198
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
199
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
200
|
+
} else {
|
|
201
|
+
[view goBack];
|
|
202
|
+
}
|
|
203
|
+
}];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag)
|
|
207
|
+
{
|
|
208
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
209
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
210
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
211
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
212
|
+
} else {
|
|
213
|
+
[view goForward];
|
|
214
|
+
}
|
|
215
|
+
}];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
RCT_EXPORT_METHOD(reload:(nonnull NSNumber *)reactTag)
|
|
219
|
+
{
|
|
220
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
221
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
222
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
223
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
224
|
+
} else {
|
|
225
|
+
[view reload];
|
|
226
|
+
}
|
|
227
|
+
}];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
RCT_EXPORT_METHOD(stopLoading:(nonnull NSNumber *)reactTag)
|
|
231
|
+
{
|
|
232
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
233
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
234
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
235
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
236
|
+
} else {
|
|
237
|
+
[view stopLoading];
|
|
238
|
+
}
|
|
239
|
+
}];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
RCT_EXPORT_METHOD(requestFocus:(nonnull NSNumber *)reactTag)
|
|
243
|
+
{
|
|
244
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, RNCWebView *> *viewRegistry) {
|
|
245
|
+
RNCWebView *view = viewRegistry[reactTag];
|
|
246
|
+
if (![view isKindOfClass:[RNCWebView class]]) {
|
|
247
|
+
RCTLogError(@"Invalid view returned from registry, expecting RNCWebView, got: %@", view);
|
|
248
|
+
} else {
|
|
249
|
+
[view requestFocus];
|
|
250
|
+
}
|
|
251
|
+
}];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
#pragma mark - Exported synchronous methods
|
|
255
|
+
|
|
256
|
+
- (BOOL) webView:(RNCWebView *)webView
|
|
257
|
+
shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
|
|
258
|
+
withCallback:(RCTDirectEventBlock)callback
|
|
259
|
+
{
|
|
260
|
+
_shouldStartLoadLock = [[NSConditionLock alloc] initWithCondition:arc4random()];
|
|
261
|
+
_shouldStartLoad = YES;
|
|
262
|
+
request[@"lockIdentifier"] = @(_shouldStartLoadLock.condition);
|
|
263
|
+
callback(request);
|
|
264
|
+
|
|
265
|
+
// Block the main thread for a maximum of 250ms until the JS thread returns
|
|
266
|
+
if ([_shouldStartLoadLock lockWhenCondition:0 beforeDate:[NSDate dateWithTimeIntervalSinceNow:.25]]) {
|
|
267
|
+
BOOL returnValue = _shouldStartLoad;
|
|
268
|
+
[_shouldStartLoadLock unlock];
|
|
269
|
+
_shouldStartLoadLock = nil;
|
|
270
|
+
return returnValue;
|
|
271
|
+
} else {
|
|
272
|
+
RCTLogWarn(@"Did not receive response to shouldStartLoad in time, defaulting to YES");
|
|
273
|
+
return YES;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
RCT_EXPORT_METHOD(startLoadWithResult:(BOOL)result lockIdentifier:(NSInteger)lockIdentifier)
|
|
278
|
+
{
|
|
279
|
+
if ([_shouldStartLoadLock tryLockWhenCondition:lockIdentifier]) {
|
|
280
|
+
_shouldStartLoad = result;
|
|
281
|
+
[_shouldStartLoadLock unlockWithCondition:0];
|
|
282
|
+
} else {
|
|
283
|
+
RCTLogWarn(@"startLoadWithResult invoked with invalid lockIdentifier: "
|
|
284
|
+
"got %lld, expected %lld", (long long)lockIdentifier, (long long)_shouldStartLoadLock.condition);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@end
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Component } from 'react';
|
|
2
|
+
// eslint-disable-next-line
|
|
3
|
+
import { IOSWebViewProps, AndroidWebViewProps } from './lib/WebViewTypes';
|
|
4
|
+
|
|
5
|
+
export { FileDownload, WebViewMessageEvent, WebViewNavigation } from "./lib/WebViewTypes";
|
|
6
|
+
|
|
7
|
+
export type WebViewProps = IOSWebViewProps & AndroidWebViewProps;
|
|
8
|
+
|
|
9
|
+
declare class WebView<P = {}> extends Component<WebViewProps & P> {
|
|
10
|
+
/**
|
|
11
|
+
* Go back one page in the webview's history.
|
|
12
|
+
*/
|
|
13
|
+
goBack: () => void;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Go forward one page in the webview's history.
|
|
17
|
+
*/
|
|
18
|
+
goForward: () => void;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Reloads the current page.
|
|
22
|
+
*/
|
|
23
|
+
reload: () => void;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Stop loading the current page.
|
|
27
|
+
*/
|
|
28
|
+
stopLoading(): void;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Executes the JavaScript string.
|
|
32
|
+
*/
|
|
33
|
+
injectJavaScript: (script: string) => void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Focuses on WebView redered page.
|
|
37
|
+
*/
|
|
38
|
+
requestFocus: () => void;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Posts a message to WebView.
|
|
42
|
+
*/
|
|
43
|
+
postMessage: (message: string) => void;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* (Android only)
|
|
47
|
+
* Removes the autocomplete popup from the currently focused form field, if present.
|
|
48
|
+
*/
|
|
49
|
+
clearFormData?: () => void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* (Android only)
|
|
53
|
+
* Clears the resource cache. Note that the cache is per-application, so this will clear the cache for all WebViews used.
|
|
54
|
+
*/
|
|
55
|
+
clearCache?: (clear: boolean) => void;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* (Android only)
|
|
59
|
+
* Tells this WebView to clear its internal back/forward list.
|
|
60
|
+
*/
|
|
61
|
+
clearHistory?: () => void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export {WebView};
|
|
65
|
+
export default WebView;
|
package/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AndroidWebViewProps } from './WebViewTypes';
|
|
3
|
+
declare const WebView: React.ForwardRefExoticComponent<AndroidWebViewProps & React.RefAttributes<{}>> & {
|
|
4
|
+
isFileUploadSupported: () => Promise<boolean>;
|
|
5
|
+
};
|
|
6
|
+
export default WebView;
|
|
7
|
+
//# sourceMappingURL=WebView.android.d.ts.map
|
package/lib/WebView.android.js
CHANGED
|
@@ -1 +1,125 @@
|
|
|
1
|
-
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
|
13
|
+
import { Image, View, NativeModules, } from 'react-native';
|
|
14
|
+
import BatchedBridge from 'react-native/Libraries/BatchedBridge/BatchedBridge';
|
|
15
|
+
// @ts-expect-error react-native doesn't have this type
|
|
16
|
+
import codegenNativeCommandsUntyped from 'react-native/Libraries/Utilities/codegenNativeCommands';
|
|
17
|
+
import invariant from 'invariant';
|
|
18
|
+
import RNCWebView from "./WebViewNativeComponent.android";
|
|
19
|
+
import { defaultOriginWhitelist, defaultRenderError, defaultRenderLoading, useWebWiewLogic, } from './WebViewShared';
|
|
20
|
+
import styles from './WebView.styles';
|
|
21
|
+
var codegenNativeCommands = codegenNativeCommandsUntyped;
|
|
22
|
+
var Commands = codegenNativeCommands({
|
|
23
|
+
supportedCommands: ['goBack', 'goForward', 'reload', 'stopLoading', /* 'injectJavaScript', */ 'requestFocus', 'postMessage', 'clearFormData', 'clearCache', 'clearHistory', 'loadUrl']
|
|
24
|
+
});
|
|
25
|
+
var resolveAssetSource = Image.resolveAssetSource;
|
|
26
|
+
/**
|
|
27
|
+
* A simple counter to uniquely identify WebView instances. Do not use this for anything else.
|
|
28
|
+
*/
|
|
29
|
+
var uniqueRef = 0;
|
|
30
|
+
/**
|
|
31
|
+
* Harcoded default for security.
|
|
32
|
+
*/
|
|
33
|
+
var allowFileAccessFromFileURLs = false;
|
|
34
|
+
var allowUniversalAccessFromFileURLs = false;
|
|
35
|
+
var injectedJavaScriptForMainFrameOnly = true;
|
|
36
|
+
var injectedJavaScriptBeforeContentLoadedForMainFrameOnly = true;
|
|
37
|
+
var mediaPlaybackRequiresUserAction = true;
|
|
38
|
+
// Android only
|
|
39
|
+
var allowsFullscreenVideo = false;
|
|
40
|
+
var allowFileAccess = false;
|
|
41
|
+
var setSupportMultipleWindows = true;
|
|
42
|
+
var mixedContentMode = 'never';
|
|
43
|
+
var WebViewComponent = forwardRef(function (_a, ref) {
|
|
44
|
+
var _b = _a.overScrollMode, overScrollMode = _b === void 0 ? 'always' : _b, _c = _a.javaScriptEnabled, javaScriptEnabled = _c === void 0 ? true : _c, _d = _a.thirdPartyCookiesEnabled, thirdPartyCookiesEnabled = _d === void 0 ? true : _d, _e = _a.scalesPageToFit, scalesPageToFit = _e === void 0 ? true : _e, _f = _a.saveFormDataDisabled, saveFormDataDisabled = _f === void 0 ? false : _f, _g = _a.cacheEnabled, cacheEnabled = _g === void 0 ? true : _g, _h = _a.androidHardwareAccelerationDisabled, androidHardwareAccelerationDisabled = _h === void 0 ? false : _h, _j = _a.androidLayerType, androidLayerType = _j === void 0 ? "none" : _j, _k = _a.originWhitelist, originWhitelist = _k === void 0 ? defaultOriginWhitelist : _k, _l = _a.setBuiltInZoomControls, setBuiltInZoomControls = _l === void 0 ? true : _l, _m = _a.setDisplayZoomControls, setDisplayZoomControls = _m === void 0 ? false : _m, _o = _a.nestedScrollEnabled, nestedScrollEnabled = _o === void 0 ? false : _o, startInLoadingState = _a.startInLoadingState, onNavigationStateChange = _a.onNavigationStateChange, onLoadStart = _a.onLoadStart, onError = _a.onError, onLoad = _a.onLoad, onLoadEnd = _a.onLoadEnd, onLoadProgress = _a.onLoadProgress, onHttpErrorProp = _a.onHttpError, onRenderProcessGoneProp = _a.onRenderProcessGone, onMessageProp = _a.onMessage, renderLoading = _a.renderLoading, renderError = _a.renderError, style = _a.style, containerStyle = _a.containerStyle, source = _a.source, onShouldStartLoadWithRequestProp = _a.onShouldStartLoadWithRequest, otherProps = __rest(_a, ["overScrollMode", "javaScriptEnabled", "thirdPartyCookiesEnabled", "scalesPageToFit", "saveFormDataDisabled", "cacheEnabled", "androidHardwareAccelerationDisabled", "androidLayerType", "originWhitelist", "setBuiltInZoomControls", "setDisplayZoomControls", "nestedScrollEnabled", "startInLoadingState", "onNavigationStateChange", "onLoadStart", "onError", "onLoad", "onLoadEnd", "onLoadProgress", "onHttpError", "onRenderProcessGone", "onMessage", "renderLoading", "renderError", "style", "containerStyle", "source", "onShouldStartLoadWithRequest"]);
|
|
45
|
+
var messagingModuleName = useRef("WebViewMessageHandler".concat(uniqueRef += 1)).current;
|
|
46
|
+
var webViewRef = useRef(null);
|
|
47
|
+
var onShouldStartLoadWithRequestCallback = useCallback(function (shouldStart, url, lockIdentifier) {
|
|
48
|
+
if (lockIdentifier) {
|
|
49
|
+
NativeModules.RNCWebView.onShouldStartLoadWithRequestCallback(shouldStart, lockIdentifier);
|
|
50
|
+
}
|
|
51
|
+
else if (shouldStart) {
|
|
52
|
+
Commands.loadUrl(webViewRef.current, url);
|
|
53
|
+
}
|
|
54
|
+
}, []);
|
|
55
|
+
var _p = useWebWiewLogic({
|
|
56
|
+
onNavigationStateChange: onNavigationStateChange,
|
|
57
|
+
onLoad: onLoad,
|
|
58
|
+
onError: onError,
|
|
59
|
+
onHttpErrorProp: onHttpErrorProp,
|
|
60
|
+
onLoadEnd: onLoadEnd,
|
|
61
|
+
onLoadProgress: onLoadProgress,
|
|
62
|
+
onLoadStart: onLoadStart,
|
|
63
|
+
onRenderProcessGoneProp: onRenderProcessGoneProp,
|
|
64
|
+
onMessageProp: onMessageProp,
|
|
65
|
+
startInLoadingState: startInLoadingState,
|
|
66
|
+
originWhitelist: originWhitelist,
|
|
67
|
+
onShouldStartLoadWithRequestProp: onShouldStartLoadWithRequestProp,
|
|
68
|
+
onShouldStartLoadWithRequestCallback: onShouldStartLoadWithRequestCallback
|
|
69
|
+
}), onLoadingStart = _p.onLoadingStart, onShouldStartLoadWithRequest = _p.onShouldStartLoadWithRequest, onMessage = _p.onMessage, viewState = _p.viewState, setViewState = _p.setViewState, lastErrorEvent = _p.lastErrorEvent, onHttpError = _p.onHttpError, onLoadingError = _p.onLoadingError, onLoadingFinish = _p.onLoadingFinish, onLoadingProgress = _p.onLoadingProgress, onRenderProcessGone = _p.onRenderProcessGone;
|
|
70
|
+
useImperativeHandle(ref, function () { return ({
|
|
71
|
+
goForward: function () { return Commands.goForward(webViewRef.current); },
|
|
72
|
+
goBack: function () { return Commands.goBack(webViewRef.current); },
|
|
73
|
+
reload: function () {
|
|
74
|
+
setViewState('LOADING');
|
|
75
|
+
Commands.reload(webViewRef.current);
|
|
76
|
+
},
|
|
77
|
+
stopLoading: function () { return Commands.stopLoading(webViewRef.current); },
|
|
78
|
+
postMessage: function (data) { return Commands.postMessage(webViewRef.current, data); },
|
|
79
|
+
// injectJavaScript: (data: string) => Commands.injectJavaScript(webViewRef.current, data),
|
|
80
|
+
requestFocus: function () { return Commands.requestFocus(webViewRef.current); },
|
|
81
|
+
clearFormData: function () { return Commands.clearFormData(webViewRef.current); },
|
|
82
|
+
clearCache: function (includeDiskFiles) { return Commands.clearCache(webViewRef.current, includeDiskFiles); },
|
|
83
|
+
clearHistory: function () { return Commands.clearHistory(webViewRef.current); }
|
|
84
|
+
}); }, [setViewState, webViewRef]);
|
|
85
|
+
var directEventCallbacks = useMemo(function () { return ({
|
|
86
|
+
onShouldStartLoadWithRequest: onShouldStartLoadWithRequest,
|
|
87
|
+
onMessage: onMessage
|
|
88
|
+
}); }, [onMessage, onShouldStartLoadWithRequest]);
|
|
89
|
+
useEffect(function () {
|
|
90
|
+
BatchedBridge.registerCallableModule(messagingModuleName, directEventCallbacks);
|
|
91
|
+
}, [messagingModuleName, directEventCallbacks]);
|
|
92
|
+
var otherView = null;
|
|
93
|
+
if (viewState === 'LOADING') {
|
|
94
|
+
otherView = (renderLoading || defaultRenderLoading)();
|
|
95
|
+
}
|
|
96
|
+
else if (viewState === 'ERROR') {
|
|
97
|
+
invariant(lastErrorEvent != null, 'lastErrorEvent expected to be non-null');
|
|
98
|
+
otherView = (renderError || defaultRenderError)(lastErrorEvent.domain, lastErrorEvent.code, lastErrorEvent.description);
|
|
99
|
+
}
|
|
100
|
+
else if (viewState !== 'IDLE') {
|
|
101
|
+
console.error("RNCWebView invalid state encountered: ".concat(viewState));
|
|
102
|
+
}
|
|
103
|
+
var webViewStyles = [styles.container, styles.webView, style];
|
|
104
|
+
var webViewContainerStyle = [styles.container, containerStyle];
|
|
105
|
+
if (typeof source !== "number" && source && 'method' in source) {
|
|
106
|
+
if (source.method === 'POST' && source.headers) {
|
|
107
|
+
console.warn('WebView: `source.headers` is not supported when using POST.');
|
|
108
|
+
}
|
|
109
|
+
else if (source.method === 'GET' && source.body) {
|
|
110
|
+
console.warn('WebView: `source.body` is not supported when using GET.');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
var NativeWebView = RNCWebView;
|
|
114
|
+
var webView = <NativeWebView key="webViewKey" {...otherProps} messagingEnabled={typeof onMessageProp === 'function'} messagingModuleName={messagingModuleName} onLoadingError={onLoadingError} onLoadingFinish={onLoadingFinish} onLoadingProgress={onLoadingProgress} onLoadingStart={onLoadingStart} onHttpError={onHttpError} onRenderProcessGone={onRenderProcessGone} onMessage={onMessage} onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} injectedJavaScriptForMainFrameOnly={injectedJavaScriptForMainFrameOnly} injectedJavaScriptBeforeContentLoadedForMainFrameOnly={injectedJavaScriptBeforeContentLoadedForMainFrameOnly} ref={webViewRef}
|
|
115
|
+
// TODO: find a better way to type this.
|
|
116
|
+
source={resolveAssetSource(source)} style={webViewStyles} overScrollMode={overScrollMode} javaScriptEnabled={javaScriptEnabled} thirdPartyCookiesEnabled={thirdPartyCookiesEnabled} scalesPageToFit={scalesPageToFit} allowsFullscreenVideo={allowsFullscreenVideo} allowFileAccess={allowFileAccess} allowFileAccessFromFileURLs={allowFileAccessFromFileURLs} allowUniversalAccessFromFileURLs={allowUniversalAccessFromFileURLs} saveFormDataDisabled={saveFormDataDisabled} cacheEnabled={cacheEnabled} androidHardwareAccelerationDisabled={androidHardwareAccelerationDisabled} androidLayerType={androidLayerType} setSupportMultipleWindows={setSupportMultipleWindows} setBuiltInZoomControls={setBuiltInZoomControls} setDisplayZoomControls={setDisplayZoomControls} mixedContentMode={mixedContentMode} nestedScrollEnabled={nestedScrollEnabled} mediaPlaybackRequiresUserAction={mediaPlaybackRequiresUserAction}/>;
|
|
117
|
+
return (<View style={webViewContainerStyle}>
|
|
118
|
+
{webView}
|
|
119
|
+
{otherView}
|
|
120
|
+
</View>);
|
|
121
|
+
});
|
|
122
|
+
// native implementation should return "true" only for Android 5+
|
|
123
|
+
var isFileUploadSupported = NativeModules.RNCWebView.isFileUploadSupported();
|
|
124
|
+
var WebView = Object.assign(WebViewComponent, { isFileUploadSupported: isFileUploadSupported });
|
|
125
|
+
export default WebView;
|
package/lib/WebView.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IOSWebViewProps, AndroidWebViewProps } from './WebViewTypes';
|
|
3
|
+
export declare type WebViewProps = IOSWebViewProps & AndroidWebViewProps;
|
|
4
|
+
declare const WebView: React.FunctionComponent<WebViewProps>;
|
|
5
|
+
export { WebView };
|
|
6
|
+
export default WebView;
|
|
7
|
+
//# sourceMappingURL=WebView.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IOSWebViewProps } from './WebViewTypes';
|
|
3
|
+
declare const WebView: React.ForwardRefExoticComponent<IOSWebViewProps & React.RefAttributes<{}>> & {
|
|
4
|
+
isFileUploadSupported: () => Promise<boolean>;
|
|
5
|
+
};
|
|
6
|
+
export default WebView;
|
|
7
|
+
//# sourceMappingURL=WebView.ios.d.ts.map
|