@exodus/react-native-webview 11.26.1-exodus.9 → 13.16.0-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.
Files changed (94) hide show
  1. package/README.md +36 -63
  2. package/android/build.gradle +83 -110
  3. package/android/gradle.properties +3 -4
  4. package/android/src/main/AndroidManifest.xml +12 -0
  5. package/android/src/main/AndroidManifestNew.xml +26 -0
  6. package/android/src/main/java/com/reactnativecommunity/webview/RNCBasicAuthCredential.java +11 -0
  7. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebChromeClient.java +407 -0
  8. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebView.java +468 -0
  9. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewClient.java +330 -0
  10. package/android/src/main/java/com/reactnativecommunity/webview/{WebViewConfig.java → RNCWebViewConfig.java} +3 -4
  11. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewFileProvider.java +1 -1
  12. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManagerImpl.kt +746 -0
  13. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewMessagingModule.kt +9 -0
  14. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModuleImpl.java +554 -0
  15. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java +57 -12
  16. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewWrapper.kt +39 -0
  17. package/android/src/main/java/com/reactnativecommunity/webview/events/SubResourceErrorEvent.kt +25 -0
  18. package/android/src/main/java/com/reactnativecommunity/webview/events/TopCustomMenuSelectionEvent.kt +24 -0
  19. package/android/src/main/java/com/reactnativecommunity/webview/events/TopHttpErrorEvent.kt +25 -0
  20. package/android/src/main/java/com/reactnativecommunity/webview/events/TopNewWindowEvent.kt +25 -0
  21. package/android/src/main/java/com/reactnativecommunity/webview/events/TopRenderProcessGoneEvent.kt +25 -0
  22. package/android/src/newarch/com/reactnativecommunity/webview/RNCWebViewManager.java +570 -0
  23. package/android/src/newarch/com/reactnativecommunity/webview/RNCWebViewModule.java +57 -0
  24. package/android/src/oldarch/com/reactnativecommunity/webview/RNCWebViewManager.java +341 -0
  25. package/android/src/oldarch/com/reactnativecommunity/webview/RNCWebViewModule.java +59 -0
  26. package/apple/RCTConvert+WKDataDetectorTypes.h +11 -0
  27. package/apple/RCTConvert+WKDataDetectorTypes.m +27 -0
  28. package/apple/RNCWebView.h +26 -100
  29. package/apple/RNCWebView.mm +555 -0
  30. package/apple/RNCWebViewDecisionManager.h +20 -0
  31. package/apple/RNCWebViewDecisionManager.m +47 -0
  32. package/apple/RNCWebViewImpl.h +164 -0
  33. package/apple/{RNCWebView.m → RNCWebViewImpl.m} +802 -225
  34. package/apple/RNCWebViewManager.h +4 -8
  35. package/apple/RNCWebViewManager.mm +221 -0
  36. package/apple/RNCWebViewModule.h +23 -0
  37. package/apple/RNCWebViewModule.mm +34 -0
  38. package/index.d.ts +2 -3
  39. package/lib/NativeRNCWebViewModule.d.ts +8 -0
  40. package/lib/NativeRNCWebViewModule.js +1 -0
  41. package/lib/RNCWebViewNativeComponent.d.ts +245 -0
  42. package/lib/RNCWebViewNativeComponent.js +1 -0
  43. package/lib/WebView.android.d.ts +0 -1
  44. package/lib/WebView.android.js +1 -135
  45. package/lib/WebView.d.ts +2 -3
  46. package/lib/WebView.ios.d.ts +0 -1
  47. package/lib/WebView.ios.js +1 -114
  48. package/lib/WebView.js +1 -11
  49. package/lib/WebView.macos.d.ts +6 -0
  50. package/lib/WebView.macos.js +1 -0
  51. package/lib/WebView.styles.d.ts +37 -11
  52. package/lib/WebView.styles.js +1 -33
  53. package/lib/WebView.windows.d.ts +17 -0
  54. package/lib/WebView.windows.js +1 -0
  55. package/lib/WebViewNativeComponent.macos.d.ts +3 -0
  56. package/lib/WebViewNativeComponent.macos.js +1 -0
  57. package/lib/WebViewNativeComponent.windows.d.ts +3 -0
  58. package/lib/WebViewNativeComponent.windows.js +1 -0
  59. package/lib/WebViewShared.d.ts +30 -9
  60. package/lib/WebViewShared.js +1 -174
  61. package/lib/WebViewTypes.d.ts +514 -98
  62. package/lib/WebViewTypes.js +1 -6
  63. package/lib/index.d.ts +0 -1
  64. package/lib/index.js +1 -3
  65. package/lib/validation.d.ts +3 -0
  66. package/lib/validation.js +1 -0
  67. package/package.json +57 -33
  68. package/react-native-webview.podspec +32 -5
  69. package/react-native.config.js +22 -18
  70. package/src/NativeRNCWebViewModule.ts +13 -0
  71. package/src/RNCWebViewNativeComponent.ts +348 -0
  72. package/src/WebView.android.tsx +345 -0
  73. package/src/WebView.ios.tsx +341 -0
  74. package/src/WebView.macos.tsx +252 -0
  75. package/src/WebView.styles.ts +41 -0
  76. package/src/WebView.tsx +25 -0
  77. package/src/WebView.windows.tsx +217 -0
  78. package/src/WebViewNativeComponent.macos.ts +7 -0
  79. package/src/WebViewNativeComponent.windows.ts +8 -0
  80. package/src/WebViewShared.tsx +476 -0
  81. package/src/WebViewTypes.ts +1402 -0
  82. package/src/__tests__/WebViewShared-test.js +323 -0
  83. package/src/__tests__/__snapshots__/WebViewShared-test.js.snap +8 -0
  84. package/src/__tests__/validation-test.js +38 -0
  85. package/src/index.ts +4 -0
  86. package/src/validation.ts +20 -0
  87. package/android/.editorconfig +0 -6
  88. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java +0 -1408
  89. package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java +0 -506
  90. package/apple/RNCWebViewManager.m +0 -278
  91. package/lib/WebViewNativeComponent.android.d.ts +0 -4
  92. package/lib/WebViewNativeComponent.android.js +0 -3
  93. package/lib/WebViewNativeComponent.ios.d.ts +0 -4
  94. package/lib/WebViewNativeComponent.ios.js +0 -3
@@ -0,0 +1,555 @@
1
+ // This guard prevent the code from being compiled in the old architecture
2
+ #ifdef RCT_NEW_ARCH_ENABLED
3
+ #import "RNCWebView.h"
4
+ #import "RNCWebViewImpl.h"
5
+
6
+ #import <react/renderer/components/RNCWebViewSpec/ComponentDescriptors.h>
7
+ #import <react/renderer/components/RNCWebViewSpec/EventEmitters.h>
8
+ #import <react/renderer/components/RNCWebViewSpec/Props.h>
9
+ #import <react/renderer/components/RNCWebViewSpec/RCTComponentViewHelpers.h>
10
+
11
+ #import <React/RCTFabricComponentsPlugins.h>
12
+
13
+ using namespace facebook::react;
14
+
15
+ auto stringToOnShouldStartLoadWithRequestNavigationTypeEnum(std::string value) {
16
+ if (value == "click") return RNCWebViewEventEmitter::OnShouldStartLoadWithRequestNavigationType::Click;
17
+ if (value == "formsubmit") return RNCWebViewEventEmitter::OnShouldStartLoadWithRequestNavigationType::Formsubmit;
18
+ if (value == "backforward") return RNCWebViewEventEmitter::OnShouldStartLoadWithRequestNavigationType::Backforward;
19
+ if (value == "reload") return RNCWebViewEventEmitter::OnShouldStartLoadWithRequestNavigationType::Reload;
20
+ if (value == "formresubmit") return RNCWebViewEventEmitter::OnShouldStartLoadWithRequestNavigationType::Formresubmit;
21
+ return RNCWebViewEventEmitter::OnShouldStartLoadWithRequestNavigationType::Other;
22
+ }
23
+
24
+ auto stringToOnLoadingStartNavigationTypeEnum(std::string value) {
25
+ if (value == "click") return RNCWebViewEventEmitter::OnLoadingStartNavigationType::Click;
26
+ if (value == "formsubmit") return RNCWebViewEventEmitter::OnLoadingStartNavigationType::Formsubmit;
27
+ if (value == "backforward") return RNCWebViewEventEmitter::OnLoadingStartNavigationType::Backforward;
28
+ if (value == "reload") return RNCWebViewEventEmitter::OnLoadingStartNavigationType::Reload;
29
+ if (value == "formresubmit") return RNCWebViewEventEmitter::OnLoadingStartNavigationType::Formresubmit;
30
+ return RNCWebViewEventEmitter::OnLoadingStartNavigationType::Other;
31
+ }
32
+
33
+ auto stringToOnLoadingFinishNavigationTypeEnum(std::string value) {
34
+ if (value == "click") return RNCWebViewEventEmitter::OnLoadingFinishNavigationType::Click;
35
+ if (value == "formsubmit") return RNCWebViewEventEmitter::OnLoadingFinishNavigationType::Formsubmit;
36
+ if (value == "backforward") return RNCWebViewEventEmitter::OnLoadingFinishNavigationType::Backforward;
37
+ if (value == "reload") return RNCWebViewEventEmitter::OnLoadingFinishNavigationType::Reload;
38
+ if (value == "formresubmit") return RNCWebViewEventEmitter::OnLoadingFinishNavigationType::Formresubmit;
39
+ return RNCWebViewEventEmitter::OnLoadingFinishNavigationType::Other;
40
+ }
41
+
42
+ @interface RNCWebView () <RCTRNCWebViewViewProtocol>
43
+
44
+ @end
45
+
46
+ @implementation RNCWebView {
47
+ RNCWebViewImpl * _view;
48
+ }
49
+
50
+ + (ComponentDescriptorProvider)componentDescriptorProvider
51
+ {
52
+ return concreteComponentDescriptorProvider<RNCWebViewComponentDescriptor>();
53
+ }
54
+
55
+ #if !TARGET_OS_OSX
56
+ // Reproduce the idea from here: https://github.com/facebook/react-native/blob/8bd3edec88148d0ab1f225d2119435681fbbba33/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm#L142
57
+ - (void)prepareForRecycle {
58
+ [super prepareForRecycle];
59
+ [_view destroyWebView];
60
+ }
61
+ #endif // !TARGET_OS_OSX
62
+
63
+ // Needed because of this: https://github.com/facebook/react-native/pull/37274
64
+ + (void)load
65
+ {
66
+ [super load];
67
+ }
68
+
69
+ - (instancetype)initWithFrame:(CGRect)frame
70
+ {
71
+ if (self = [super initWithFrame:frame]) {
72
+ static const auto defaultProps = std::make_shared<const RNCWebViewProps>();
73
+ _props = defaultProps;
74
+
75
+ _view = [[RNCWebViewImpl alloc] init];
76
+
77
+ _view.onShouldStartLoadWithRequest = [self](NSDictionary* dictionary) {
78
+ if (_eventEmitter) {
79
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
80
+ facebook::react::RNCWebViewEventEmitter::OnShouldStartLoadWithRequest data = {
81
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
82
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
83
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
84
+ .navigationType = stringToOnShouldStartLoadWithRequestNavigationTypeEnum(std::string([[dictionary valueForKey:@"navigationType"] UTF8String])),
85
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
86
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
87
+ .isTopFrame = static_cast<bool>([[dictionary valueForKey:@"isTopFrame"] boolValue]),
88
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue]),
89
+ .mainDocumentURL = std::string([[dictionary valueForKey:@"mainDocumentURL"] UTF8String])
90
+ };
91
+ webViewEventEmitter->onShouldStartLoadWithRequest(data);
92
+ };
93
+ };
94
+ _view.onLoadingStart = [self](NSDictionary* dictionary) {
95
+ if (_eventEmitter) {
96
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
97
+ facebook::react::RNCWebViewEventEmitter::OnLoadingStart data = {
98
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
99
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
100
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
101
+ .navigationType = stringToOnLoadingStartNavigationTypeEnum(std::string([[dictionary valueForKey:@"navigationType"] UTF8String])),
102
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
103
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
104
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue]),
105
+ .mainDocumentURL = std::string([[dictionary valueForKey:@"mainDocumentURL"] UTF8String], [[dictionary valueForKey:@"mainDocumentURL"] lengthOfBytesUsingEncoding:NSUTF8StringEncoding])
106
+ };
107
+ webViewEventEmitter->onLoadingStart(data);
108
+ }
109
+ };
110
+ _view.onLoadingError = [self](NSDictionary* dictionary) {
111
+ if (_eventEmitter) {
112
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
113
+ facebook::react::RNCWebViewEventEmitter::OnLoadingError data = {
114
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
115
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
116
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
117
+ .code = [[dictionary valueForKey:@"code"] intValue],
118
+ .description = std::string([[dictionary valueForKey:@"description"] UTF8String] ?: ""),
119
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
120
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
121
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue]),
122
+ .domain = std::string([[dictionary valueForKey:@"domain"] UTF8String])
123
+ };
124
+ webViewEventEmitter->onLoadingError(data);
125
+ }
126
+ };
127
+ _view.onMessage = [self](NSDictionary* dictionary) {
128
+ if (_eventEmitter) {
129
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
130
+ facebook::react::RNCWebViewEventEmitter::OnMessage data = {
131
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
132
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
133
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
134
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
135
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
136
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue]),
137
+ .data = std::string([[dictionary valueForKey:@"data"] UTF8String])
138
+ };
139
+ webViewEventEmitter->onMessage(data);
140
+ }
141
+ };
142
+ _view.onLoadingFinish = [self](NSDictionary* dictionary) {
143
+ if (_eventEmitter) {
144
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
145
+ facebook::react::RNCWebViewEventEmitter::OnLoadingFinish data = {
146
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
147
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
148
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
149
+ .navigationType = stringToOnLoadingFinishNavigationTypeEnum(std::string([[dictionary valueForKey:@"navigationType"] UTF8String], [[dictionary valueForKey:@"navigationType"] lengthOfBytesUsingEncoding:NSUTF8StringEncoding])),
150
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
151
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
152
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue]),
153
+ .mainDocumentURL = std::string([[dictionary valueForKey:@"mainDocumentURL"] UTF8String], [[dictionary valueForKey:@"mainDocumentURL"] lengthOfBytesUsingEncoding:NSUTF8StringEncoding])
154
+ };
155
+ webViewEventEmitter->onLoadingFinish(data);
156
+ }
157
+ };
158
+ _view.onLoadingProgress = [self](NSDictionary* dictionary) {
159
+ if (_eventEmitter) {
160
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
161
+ facebook::react::RNCWebViewEventEmitter::OnLoadingProgress data = {
162
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
163
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
164
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
165
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
166
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
167
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue]),
168
+ .progress = [[dictionary valueForKey:@"progress"] doubleValue]
169
+ };
170
+ webViewEventEmitter->onLoadingProgress(data);
171
+ }
172
+ };
173
+ _view.onContentProcessDidTerminate = [self](NSDictionary* dictionary) {
174
+ if (_eventEmitter) {
175
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
176
+ facebook::react::RNCWebViewEventEmitter::OnContentProcessDidTerminate data = {
177
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
178
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
179
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
180
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
181
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
182
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue])
183
+ };
184
+ webViewEventEmitter->onContentProcessDidTerminate(data);
185
+ }
186
+ };
187
+ _view.onCustomMenuSelection = [self](NSDictionary* dictionary) {
188
+ if (_eventEmitter) {
189
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
190
+ facebook::react::RNCWebViewEventEmitter::OnCustomMenuSelection data = {
191
+ .selectedText = std::string([[dictionary valueForKey:@"selectedText"] UTF8String]),
192
+ .key = std::string([[dictionary valueForKey:@"key"] UTF8String]),
193
+ .label = std::string([[dictionary valueForKey:@"label"] UTF8String])
194
+
195
+ };
196
+ webViewEventEmitter->onCustomMenuSelection(data);
197
+ }
198
+ };
199
+ _view.onScroll = [self](NSDictionary* dictionary) {
200
+ if (_eventEmitter) {
201
+ NSDictionary* contentOffset = [dictionary valueForKey:@"contentOffset"];
202
+ NSDictionary* contentInset = [dictionary valueForKey:@"contentInset"];
203
+ NSDictionary* contentSize = [dictionary valueForKey:@"contentSize"];
204
+ NSDictionary* layoutMeasurement = [dictionary valueForKey:@"layoutMeasurement"];
205
+ double zoomScale = [[dictionary valueForKey:@"zoomScale"] doubleValue];
206
+
207
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
208
+ facebook::react::RNCWebViewEventEmitter::OnScroll data = {
209
+ .contentOffset = {
210
+ .x = [[contentOffset valueForKey:@"x"] doubleValue],
211
+ .y = [[contentOffset valueForKey:@"y"] doubleValue]
212
+ },
213
+ .contentInset = {
214
+ .left = [[contentInset valueForKey:@"left"] doubleValue],
215
+ .right = [[contentInset valueForKey:@"right"] doubleValue],
216
+ .top = [[contentInset valueForKey:@"top"] doubleValue],
217
+ .bottom = [[contentInset valueForKey:@"bottom"] doubleValue]
218
+ },
219
+ .contentSize = {
220
+ .width = [[contentSize valueForKey:@"width"] doubleValue],
221
+ .height = [[contentSize valueForKey:@"height"] doubleValue]
222
+ },
223
+ .layoutMeasurement = {
224
+ .width = [[layoutMeasurement valueForKey:@"width"] doubleValue],
225
+ .height = [[layoutMeasurement valueForKey:@"height"] doubleValue] },
226
+ .zoomScale = zoomScale
227
+ };
228
+ webViewEventEmitter->onScroll(data);
229
+ }
230
+ };
231
+ _view.onHttpError = [self](NSDictionary* dictionary) {
232
+ if (_eventEmitter) {
233
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
234
+ facebook::react::RNCWebViewEventEmitter::OnHttpError data = {
235
+ .url = std::string([[dictionary valueForKey:@"url"] UTF8String]),
236
+ .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue],
237
+ .title = std::string([[dictionary valueForKey:@"title"] UTF8String]),
238
+ .statusCode = [[dictionary valueForKey:@"statusCode"] intValue],
239
+ .description = std::string([[dictionary valueForKey:@"description"] UTF8String] ?: ""),
240
+ .canGoBack = static_cast<bool>([[dictionary valueForKey:@"canGoBack"] boolValue]),
241
+ .canGoForward = static_cast<bool>([[dictionary valueForKey:@"canGoForward"] boolValue]),
242
+ .loading = static_cast<bool>([[dictionary valueForKey:@"loading"] boolValue])
243
+ };
244
+ webViewEventEmitter->onHttpError(data);
245
+ }
246
+ };
247
+ self.contentView = _view;
248
+ }
249
+ return self;
250
+ }
251
+
252
+ - (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter
253
+ {
254
+ [super updateEventEmitter:eventEmitter];
255
+ }
256
+
257
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
258
+ {
259
+ const auto &oldViewProps = *std::static_pointer_cast<RNCWebViewProps const>(_props);
260
+ const auto &newViewProps = *std::static_pointer_cast<RNCWebViewProps const>(props);
261
+
262
+ #define REMAP_WEBVIEW_PROP(name) \
263
+ if (oldViewProps.name != newViewProps.name) { \
264
+ _view.name = newViewProps.name; \
265
+ }
266
+
267
+ #define REMAP_WEBVIEW_STRING_PROP(name) \
268
+ if (oldViewProps.name != newViewProps.name) { \
269
+ _view.name = RCTNSStringFromString(newViewProps.name); \
270
+ }
271
+
272
+ REMAP_WEBVIEW_PROP(scrollEnabled)
273
+ REMAP_WEBVIEW_STRING_PROP(injectedJavaScript)
274
+ REMAP_WEBVIEW_STRING_PROP(injectedJavaScriptBeforeContentLoaded)
275
+ REMAP_WEBVIEW_PROP(injectedJavaScriptForMainFrameOnly)
276
+ REMAP_WEBVIEW_PROP(injectedJavaScriptBeforeContentLoadedForMainFrameOnly)
277
+ REMAP_WEBVIEW_STRING_PROP(injectedJavaScriptObject)
278
+ REMAP_WEBVIEW_PROP(javaScriptEnabled)
279
+ REMAP_WEBVIEW_PROP(javaScriptCanOpenWindowsAutomatically)
280
+ REMAP_WEBVIEW_PROP(allowFileAccessFromFileURLs)
281
+ REMAP_WEBVIEW_PROP(allowUniversalAccessFromFileURLs)
282
+ REMAP_WEBVIEW_PROP(allowsInlineMediaPlayback)
283
+ REMAP_WEBVIEW_PROP(allowsPictureInPictureMediaPlayback)
284
+ REMAP_WEBVIEW_PROP(webviewDebuggingEnabled)
285
+ REMAP_WEBVIEW_PROP(allowsAirPlayForMediaPlayback)
286
+ REMAP_WEBVIEW_PROP(mediaPlaybackRequiresUserAction)
287
+ REMAP_WEBVIEW_PROP(automaticallyAdjustContentInsets)
288
+ REMAP_WEBVIEW_PROP(autoManageStatusBarEnabled)
289
+ REMAP_WEBVIEW_PROP(hideKeyboardAccessoryView)
290
+ REMAP_WEBVIEW_PROP(allowsBackForwardNavigationGestures)
291
+ REMAP_WEBVIEW_PROP(incognito)
292
+ REMAP_WEBVIEW_PROP(pagingEnabled)
293
+ REMAP_WEBVIEW_STRING_PROP(applicationNameForUserAgent)
294
+ REMAP_WEBVIEW_PROP(cacheEnabled)
295
+ REMAP_WEBVIEW_PROP(allowsLinkPreview)
296
+ REMAP_WEBVIEW_STRING_PROP(allowingReadAccessToURL)
297
+ REMAP_WEBVIEW_PROP(messagingEnabled)
298
+ #if !TARGET_OS_OSX
299
+ REMAP_WEBVIEW_PROP(fraudulentWebsiteWarningEnabled)
300
+ #endif // !TARGET_OS_OSX
301
+ REMAP_WEBVIEW_PROP(enableApplePay)
302
+ REMAP_WEBVIEW_PROP(pullToRefreshEnabled)
303
+ REMAP_WEBVIEW_PROP(refreshControlLightMode)
304
+ REMAP_WEBVIEW_PROP(bounces)
305
+ REMAP_WEBVIEW_PROP(useSharedProcessPool)
306
+ REMAP_WEBVIEW_STRING_PROP(userAgent)
307
+ REMAP_WEBVIEW_PROP(sharedCookiesEnabled)
308
+ #if !TARGET_OS_OSX
309
+ REMAP_WEBVIEW_PROP(decelerationRate)
310
+ #endif // !TARGET_OS_OSX
311
+ REMAP_WEBVIEW_PROP(directionalLockEnabled)
312
+ REMAP_WEBVIEW_PROP(showsHorizontalScrollIndicator)
313
+ REMAP_WEBVIEW_PROP(showsVerticalScrollIndicator)
314
+ REMAP_WEBVIEW_PROP(keyboardDisplayRequiresUserAction)
315
+
316
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */
317
+ REMAP_WEBVIEW_PROP(automaticallyAdjustContentInsets)
318
+ #endif
319
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000 /* iOS 14 */
320
+ REMAP_WEBVIEW_PROP(limitsNavigationsToAppBoundDomains)
321
+ #endif
322
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500 /* iOS 14.5 */
323
+ REMAP_WEBVIEW_PROP(textInteractionEnabled)
324
+ #endif
325
+
326
+ #if !TARGET_OS_OSX
327
+ if (oldViewProps.dataDetectorTypes != newViewProps.dataDetectorTypes) {
328
+ WKDataDetectorTypes dataDetectorTypes = WKDataDetectorTypeNone;
329
+ if (dataDetectorTypes & RNCWebViewDataDetectorTypes::Address) {
330
+ dataDetectorTypes |= WKDataDetectorTypeAddress;
331
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::Link) {
332
+ dataDetectorTypes |= WKDataDetectorTypeLink;
333
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::CalendarEvent) {
334
+ dataDetectorTypes |= WKDataDetectorTypeCalendarEvent;
335
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::TrackingNumber) {
336
+ dataDetectorTypes |= WKDataDetectorTypeTrackingNumber;
337
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::FlightNumber) {
338
+ dataDetectorTypes |= WKDataDetectorTypeFlightNumber;
339
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::LookupSuggestion) {
340
+ dataDetectorTypes |= WKDataDetectorTypeLookupSuggestion;
341
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::PhoneNumber) {
342
+ dataDetectorTypes |= WKDataDetectorTypePhoneNumber;
343
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::All) {
344
+ dataDetectorTypes |= WKDataDetectorTypeAll;
345
+ } else if (dataDetectorTypes & RNCWebViewDataDetectorTypes::None) {
346
+ dataDetectorTypes = WKDataDetectorTypeNone;
347
+ }
348
+ [_view setDataDetectorTypes:dataDetectorTypes];
349
+ }
350
+ #endif // !TARGET_OS_OSX
351
+
352
+ if (oldViewProps.contentInset.top != newViewProps.contentInset.top || oldViewProps.contentInset.left != newViewProps.contentInset.left || oldViewProps.contentInset.right != newViewProps.contentInset.right || oldViewProps.contentInset.bottom != newViewProps.contentInset.bottom) {
353
+ UIEdgeInsets edgesInsets = {
354
+ .top = newViewProps.contentInset.top,
355
+ .left = newViewProps.contentInset.left,
356
+ .right = newViewProps.contentInset.right,
357
+ .bottom = newViewProps.contentInset.bottom
358
+ };
359
+ [_view setContentInset: edgesInsets];
360
+ }
361
+
362
+ if (oldViewProps.basicAuthCredential.username != newViewProps.basicAuthCredential.username || oldViewProps.basicAuthCredential.password != newViewProps.basicAuthCredential.password) {
363
+ [_view setBasicAuthCredential: @{
364
+ @"username": RCTNSStringFromString(newViewProps.basicAuthCredential.username),
365
+ @"password": RCTNSStringFromString(newViewProps.basicAuthCredential.password)
366
+ }];
367
+ }
368
+
369
+ #if !TARGET_OS_OSX
370
+ if (oldViewProps.contentInsetAdjustmentBehavior != newViewProps.contentInsetAdjustmentBehavior) {
371
+ if (newViewProps.contentInsetAdjustmentBehavior == RNCWebViewContentInsetAdjustmentBehavior::Never) {
372
+ [_view setContentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentNever];
373
+ } else if (newViewProps.contentInsetAdjustmentBehavior == RNCWebViewContentInsetAdjustmentBehavior::Automatic) {
374
+ [_view setContentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentAutomatic];
375
+ } else if (newViewProps.contentInsetAdjustmentBehavior == RNCWebViewContentInsetAdjustmentBehavior::ScrollableAxes) {
376
+ [_view setContentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentScrollableAxes];
377
+ } else if (newViewProps.contentInsetAdjustmentBehavior == RNCWebViewContentInsetAdjustmentBehavior::Always) {
378
+ [_view setContentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentAlways];
379
+ }
380
+ }
381
+ #endif // !TARGET_OS_OSX
382
+
383
+ if (oldViewProps.menuItems != newViewProps.menuItems) {
384
+ NSMutableArray *newMenuItems = [NSMutableArray array];
385
+
386
+ for (const auto &menuItem: newViewProps.menuItems) {
387
+ [newMenuItems addObject:@{
388
+ @"key": RCTNSStringFromString(menuItem.key),
389
+ @"label": RCTNSStringFromString(menuItem.label),
390
+ }];
391
+
392
+ }
393
+ [_view setMenuItems:newMenuItems];
394
+ }
395
+ if(oldViewProps.suppressMenuItems != newViewProps.suppressMenuItems) {
396
+ NSMutableArray *suppressMenuItems = [NSMutableArray array];
397
+
398
+ for (const auto &menuItem: newViewProps.suppressMenuItems) {
399
+ [suppressMenuItems addObject: RCTNSStringFromString(menuItem)];
400
+ }
401
+
402
+ [_view setSuppressMenuItems:suppressMenuItems];
403
+ }
404
+ if (oldViewProps.hasOnFileDownload != newViewProps.hasOnFileDownload) {
405
+ if (newViewProps.hasOnFileDownload) {
406
+ _view.onFileDownload = [self](NSDictionary* dictionary) {
407
+ if (_eventEmitter) {
408
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
409
+ facebook::react::RNCWebViewEventEmitter::OnFileDownload data = {
410
+ .downloadUrl = std::string([[dictionary valueForKey:@"downloadUrl"] UTF8String])
411
+ };
412
+ webViewEventEmitter->onFileDownload(data);
413
+ }
414
+ };
415
+ } else {
416
+ _view.onFileDownload = nil;
417
+ }
418
+ }
419
+ if (oldViewProps.hasOnOpenWindowEvent != newViewProps.hasOnOpenWindowEvent) {
420
+ if (newViewProps.hasOnOpenWindowEvent) {
421
+ _view.onOpenWindow = [self](NSDictionary* dictionary) {
422
+ if (_eventEmitter) {
423
+ auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
424
+ facebook::react::RNCWebViewEventEmitter::OnOpenWindow data = {
425
+ .targetUrl = std::string([[dictionary valueForKey:@"targetUrl"] UTF8String])
426
+ };
427
+ webViewEventEmitter->onOpenWindow(data);
428
+ }
429
+ };
430
+ } else {
431
+ _view.onOpenWindow = nil;
432
+ }
433
+ }
434
+ //
435
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* iOS 13 */
436
+ if (oldViewProps.contentMode != newViewProps.contentMode) {
437
+ if (newViewProps.contentMode == RNCWebViewContentMode::Recommended) {
438
+ [_view setContentMode: WKContentModeRecommended];
439
+ } else if (newViewProps.contentMode == RNCWebViewContentMode::Mobile) {
440
+ [_view setContentMode:WKContentModeMobile];
441
+ } else if (newViewProps.contentMode == RNCWebViewContentMode::Desktop) {
442
+ [_view setContentMode:WKContentModeDesktop];
443
+ }
444
+ }
445
+ #endif
446
+
447
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 150000 /* iOS 15 */
448
+ if (oldViewProps.mediaCapturePermissionGrantType != newViewProps.mediaCapturePermissionGrantType) {
449
+ if (newViewProps.mediaCapturePermissionGrantType == RNCWebViewMediaCapturePermissionGrantType::Prompt) {
450
+ [_view setMediaCapturePermissionGrantType:RNCWebViewPermissionGrantType_Prompt];
451
+ } else if (newViewProps.mediaCapturePermissionGrantType == RNCWebViewMediaCapturePermissionGrantType::Grant) {
452
+ [_view setMediaCapturePermissionGrantType:RNCWebViewPermissionGrantType_Grant];
453
+ } else if (newViewProps.mediaCapturePermissionGrantType == RNCWebViewMediaCapturePermissionGrantType::Deny) {
454
+ [_view setMediaCapturePermissionGrantType:RNCWebViewPermissionGrantType_Deny];
455
+ }else if (newViewProps.mediaCapturePermissionGrantType == RNCWebViewMediaCapturePermissionGrantType::GrantIfSameHostElsePrompt) {
456
+ [_view setMediaCapturePermissionGrantType:RNCWebViewPermissionGrantType_GrantIfSameHost_ElsePrompt];
457
+ }else if (newViewProps.mediaCapturePermissionGrantType == RNCWebViewMediaCapturePermissionGrantType::GrantIfSameHostElseDeny) {
458
+ [_view setMediaCapturePermissionGrantType:RNCWebViewPermissionGrantType_GrantIfSameHost_ElseDeny];
459
+ }
460
+ }
461
+ #endif
462
+ if (oldViewProps.indicatorStyle != newViewProps.indicatorStyle) {
463
+ if (newViewProps.indicatorStyle == RNCWebViewIndicatorStyle::Black) {
464
+ [_view setIndicatorStyle:@"black"];
465
+ } else if (newViewProps.indicatorStyle == RNCWebViewIndicatorStyle::White) {
466
+ [_view setIndicatorStyle:@"white"];
467
+ } else {
468
+ [_view setIndicatorStyle:@"default"];
469
+ }
470
+ }
471
+
472
+ NSMutableDictionary* source = [[NSMutableDictionary alloc] init];
473
+ if (!newViewProps.newSource.uri.empty()) {
474
+ [source setValue:RCTNSStringFromString(newViewProps.newSource.uri) forKey:@"uri"];
475
+ }
476
+ NSMutableDictionary* headers = [[NSMutableDictionary alloc] init];
477
+ for (auto & element : newViewProps.newSource.headers) {
478
+ [headers setValue:RCTNSStringFromString(element.value) forKey:RCTNSStringFromString(element.name)];
479
+ }
480
+ if (headers.count > 0) {
481
+ [source setObject:headers forKey:@"headers"];
482
+ }
483
+ if (!newViewProps.newSource.baseUrl.empty()) {
484
+ [source setValue:RCTNSStringFromString(newViewProps.newSource.baseUrl) forKey:@"baseUrl"];
485
+ }
486
+ if (!newViewProps.newSource.body.empty()) {
487
+ [source setValue:RCTNSStringFromString(newViewProps.newSource.body) forKey:@"body"];
488
+ }
489
+ if (!newViewProps.newSource.html.empty()) {
490
+ [source setValue:RCTNSStringFromString(newViewProps.newSource.html) forKey:@"html"];
491
+ }
492
+ if (!newViewProps.newSource.method.empty()) {
493
+ [source setValue:RCTNSStringFromString(newViewProps.newSource.method) forKey:@"method"];
494
+ }
495
+ [_view setSource:source];
496
+
497
+ [super updateProps:props oldProps:oldProps];
498
+ }
499
+
500
+ - (void)handleCommand:(nonnull const NSString *)commandName args:(nonnull const NSArray *)args {
501
+ RCTRNCWebViewHandleCommand(self, commandName, args);
502
+ }
503
+
504
+
505
+ Class<RCTComponentViewProtocol> RNCWebViewCls(void)
506
+ {
507
+ return RNCWebView.class;
508
+ }
509
+
510
+ - (void)goBack {
511
+ [_view goBack];
512
+ }
513
+
514
+ - (void)goForward {
515
+ [_view goForward];
516
+ }
517
+
518
+ - (void)injectJavaScript:(nonnull NSString *)javascript {
519
+ [_view injectJavaScript:javascript];
520
+ }
521
+
522
+ - (void)loadUrl:(nonnull NSString *)url {
523
+ // android only
524
+ }
525
+
526
+ - (void)postMessage:(nonnull NSString *)data {
527
+ [_view postMessage:data];
528
+ }
529
+
530
+ - (void)reload {
531
+ [_view reload];
532
+ }
533
+
534
+ - (void)requestFocus {
535
+ [_view requestFocus];
536
+ }
537
+
538
+ - (void)stopLoading {
539
+ [_view stopLoading];
540
+ }
541
+
542
+ - (void)clearFormData {
543
+ // android only
544
+ }
545
+
546
+ - (void)clearCache:(BOOL)includeDiskFiles {
547
+ // android only
548
+ }
549
+
550
+ - (void)clearHistory {
551
+ // android only
552
+ }
553
+
554
+ @end
555
+ #endif
@@ -0,0 +1,20 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <React/RCTLog.h>
3
+ #import <WebKit/WebKit.h>
4
+
5
+ typedef void (^DecisionBlock)(BOOL);
6
+
7
+ @interface RNCWebViewDecisionManager : NSObject {
8
+ int nextLockIdentifier;
9
+ NSMutableDictionary *decisionHandlers;
10
+ }
11
+
12
+ @property (nonatomic) int nextLockIdentifier;
13
+ @property (nonatomic, retain) NSMutableDictionary *decisionHandlers;
14
+
15
+ + (id) getInstance;
16
+
17
+ - (int)setDecisionHandler:(DecisionBlock)handler;
18
+ - (void) setResult:(BOOL)shouldStart
19
+ forLockIdentifier:(int)lockIdentifier;
20
+ @end
@@ -0,0 +1,47 @@
1
+ #import "RNCWebViewDecisionManager.h"
2
+
3
+
4
+
5
+ @implementation RNCWebViewDecisionManager
6
+
7
+ @synthesize nextLockIdentifier;
8
+ @synthesize decisionHandlers;
9
+
10
+ + (id)getInstance {
11
+ static RNCWebViewDecisionManager *lockManager = nil;
12
+ static dispatch_once_t onceToken;
13
+ dispatch_once(&onceToken, ^{
14
+ lockManager = [[self alloc] init];
15
+ });
16
+ return lockManager;
17
+ }
18
+
19
+ - (int)setDecisionHandler:(DecisionBlock)decisionHandler {
20
+ int lockIdentifier = self.nextLockIdentifier++;
21
+
22
+ [self.decisionHandlers setObject:decisionHandler forKey:@(lockIdentifier)];
23
+ return lockIdentifier;
24
+ }
25
+
26
+ - (void) setResult:(BOOL)shouldStart
27
+ forLockIdentifier:(int)lockIdentifier {
28
+ DecisionBlock handler = [self.decisionHandlers objectForKey:@(lockIdentifier)];
29
+ if (handler == nil) {
30
+ RCTLogWarn(@"Lock not found");
31
+ return;
32
+ }
33
+ handler(shouldStart);
34
+ [self.decisionHandlers removeObjectForKey:@(lockIdentifier)];
35
+ }
36
+
37
+ - (id)init {
38
+ if (self = [super init]) {
39
+ self.nextLockIdentifier = 1;
40
+ self.decisionHandlers = [[NSMutableDictionary alloc] init];
41
+ }
42
+ return self;
43
+ }
44
+
45
+ - (void)dealloc {}
46
+
47
+ @end