Skip to content

Commit 07a006f

Browse files
authored
Introduce onCanGoBackChange & onCanGoForwardChange props
2 parents 59bd235 + 0ce7828 commit 07a006f

File tree

3 files changed

+62
-28
lines changed

3 files changed

+62
-28
lines changed

WKWebView.ios.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ class WKWebView extends React.Component {
173173
* Report the progress
174174
*/
175175
onProgress: PropTypes.func,
176+
onCanGoBackChange: PropTypes.func,
177+
onCanGoForwardChange: PropTypes.func,
176178
/**
177179
* A function that is invoked when the webview calls `window.postMessage`.
178180
* Setting this property will inject a `postMessage` global into your
@@ -355,6 +357,8 @@ class WKWebView extends React.Component {
355357
onLoadingError={this._onLoadingError}
356358
messagingEnabled={messagingEnabled}
357359
onProgress={this._onProgress}
360+
onCanGoBackChange={this._onCanGoBackChange}
361+
onCanGoForwardChange={this._onCanGoForwardChange}
358362
onMessage={this._onMessage}
359363
onScroll={this._onScroll}
360364
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
@@ -503,6 +507,16 @@ class WKWebView extends React.Component {
503507
onProgress && onProgress(event.nativeEvent.progress);
504508
};
505509

510+
_onCanGoBackChange = (event: Event) => {
511+
const onCanGoBackChange = this.props.onCanGoBackChange;
512+
onCanGoBackChange && onCanGoBackChange(event.nativeEvent.canGoBack);
513+
}
514+
515+
_onCanGoForwardChange = (event: Event) => {
516+
const onCanGoForwardChange = this.props.onCanGoForwardChange;
517+
onCanGoForwardChange && onCanGoForwardChange(event.nativeEvent.canGoForward);
518+
}
519+
506520
_onMessage = (event: Event) => {
507521
var { onMessage } = this.props;
508522
onMessage && onMessage(event);

ios/RCTWKWebView/RCTWKWebView.m

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ @interface RCTWKWebView () <WKNavigationDelegate, RCTAutoInsetsProtocol, WKScrip
3434
@property (nonatomic, copy) RCTDirectEventBlock onMessage;
3535
@property (nonatomic, copy) RCTDirectEventBlock onScroll;
3636
@property (nonatomic, copy) RCTDirectEventBlock onNavigationResponse;
37+
@property (nonatomic, copy) RCTDirectEventBlock onCanGoBackChange;
38+
@property (nonatomic, copy) RCTDirectEventBlock onCanGoForwardChange;
3739
@property (assign) BOOL sendCookies;
3840
@property (assign) BOOL useWKCookieStore;
3941
@property (nonatomic, strong) WKUserScript *atStartScript;
@@ -64,18 +66,18 @@ - (instancetype)initWithProcessPool:(WKProcessPool *)processPool
6466
super.backgroundColor = [UIColor clearColor];
6567
_automaticallyAdjustContentInsets = YES;
6668
_contentInset = UIEdgeInsetsZero;
67-
69+
6870
WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init];
6971
config.processPool = processPool;
7072
WKUserContentController* userController = [[WKUserContentController alloc]init];
7173
[userController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"reactNative"];
7274
config.userContentController = userController;
73-
75+
7476
_webView = [[WKWebView alloc] initWithFrame:self.bounds configuration:config];
7577
_webView.UIDelegate = self;
7678
_webView.navigationDelegate = self;
7779
_webView.scrollView.delegate = self;
78-
80+
7981
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
8082
// `contentInsetAdjustmentBehavior` is only available since iOS 11.
8183
// We set the default behavior to "never" so that iOS
@@ -87,6 +89,8 @@ - (instancetype)initWithProcessPool:(WKProcessPool *)processPool
8789
#endif
8890
[self setupPostMessageScript];
8991
[_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
92+
[_webView addObserver:self forKeyPath:@"canGoBack" options:NSKeyValueObservingOptionNew context:nil];
93+
[_webView addObserver:self forKeyPath:@"canGoForward" options:NSKeyValueObservingOptionNew context:nil];
9094
[self addSubview:_webView];
9195
}
9296
return self;
@@ -164,7 +168,7 @@ - (void)loadRequest:(NSURLRequest *)request
164168
request = mutableRequest;
165169
}
166170
}
167-
171+
168172
[_webView loadRequest:request];
169173
}
170174

@@ -180,29 +184,29 @@ -(void)setHideKeyboardAccessoryView:(BOOL)hideKeyboardAccessoryView
180184
if (!hideKeyboardAccessoryView) {
181185
return;
182186
}
183-
187+
184188
UIView* subview;
185189
for (UIView* view in _webView.scrollView.subviews) {
186190
if([[view.class description] hasPrefix:@"WKContent"])
187191
subview = view;
188192
}
189-
193+
190194
if(subview == nil) return;
191-
195+
192196
NSString* name = [NSString stringWithFormat:@"%@_SwizzleHelperWK", subview.class.superclass];
193197
Class newClass = NSClassFromString(name);
194-
198+
195199
if(newClass == nil)
196200
{
197201
newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);
198202
if(!newClass) return;
199-
203+
200204
Method method = class_getInstanceMethod([_SwizzleHelperWK class], @selector(inputAccessoryView));
201205
class_addMethod(newClass, @selector(inputAccessoryView), method_getImplementation(method), method_getTypeEncoding(method));
202-
206+
203207
objc_registerClassPair(newClass);
204208
}
205-
209+
206210
object_setClass(subview, newClass);
207211
}
208212

@@ -213,7 +217,7 @@ -(void)setKeyboardDisplayRequiresUserAction:(BOOL)keyboardDisplayRequiresUserAct
213217
if (!keyboardDisplayRequiresUserAction) {
214218
Class class = NSClassFromString(@"WKContentView");
215219
NSOperatingSystemVersion iOS_11_3_0 = (NSOperatingSystemVersion){11, 3, 0};
216-
220+
217221
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion: iOS_11_3_0]) {
218222
SEL selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:");
219223
Method method = class_getInstanceMethod(class, selector);
@@ -371,20 +375,20 @@ - (void)setSource:(NSDictionary *)source
371375
if ([source[@"customUserAgent"] length] != 0 && [_webView respondsToSelector:@selector(setCustomUserAgent:)]) {
372376
[_webView setCustomUserAgent:source[@"customUserAgent"]];
373377
}
374-
378+
375379
// Allow loading local files:
376380
// <WKWebView source={{ file: RNFS.MainBundlePath + '/data/index.html', allowingReadAccessToURL: RNFS.MainBundlePath }} />
377381
// Only works for iOS 9+. So iOS 8 will simply ignore those two values
378382
NSString *file = [RCTConvert NSString:source[@"file"]];
379383
NSString *allowingReadAccessToURL = [RCTConvert NSString:source[@"allowingReadAccessToURL"]];
380-
384+
381385
if (file && [_webView respondsToSelector:@selector(loadFileURL:allowingReadAccessToURL:)]) {
382386
NSURL *fileURL = [RCTConvert NSURL:file];
383387
NSURL *baseURL = [RCTConvert NSURL:allowingReadAccessToURL];
384388
[_webView loadFileURL:fileURL allowingReadAccessToURL:baseURL];
385389
return;
386390
}
387-
391+
388392
// Check for a static html source first
389393
NSString *html = [RCTConvert NSString:source[@"html"]];
390394
if (html) {
@@ -395,7 +399,7 @@ - (void)setSource:(NSDictionary *)source
395399
[_webView loadHTMLString:html baseURL:baseURL];
396400
return;
397401
}
398-
402+
399403
NSURLRequest *request = [RCTConvert NSURLRequest:source];
400404
// Because of the way React works, as pages redirect, we actually end up
401405
// passing the redirect urls back here, so we ignore them if trying to load
@@ -448,7 +452,7 @@ - (UIColor *)backgroundColor
448452
@"canGoBack": @(_webView.canGoBack),
449453
@"canGoForward" : @(_webView.canGoForward),
450454
}];
451-
455+
452456
return event;
453457
}
454458

@@ -470,6 +474,20 @@ - (void)observeValueForKeyPath:(NSString *)keyPath
470474
}
471475
_onProgress(@{@"progress": [change objectForKey:NSKeyValueChangeNewKey]});
472476
}
477+
478+
if ([keyPath isEqualToString:@"canGoBack"]) {
479+
if (!_onCanGoBackChange) {
480+
return;
481+
}
482+
_onCanGoBackChange(@{@"canGoBack": [change objectForKey:NSKeyValueChangeNewKey]});
483+
}
484+
485+
if ([keyPath isEqualToString:@"canGoForward"]) {
486+
if (!_onCanGoForwardChange) {
487+
return;
488+
}
489+
_onCanGoForwardChange(@{@"canGoForward": [change objectForKey:NSKeyValueChangeNewKey]});
490+
}
473491
}
474492

475493
- (void)dealloc
@@ -525,9 +543,9 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
525543
NSURLRequest *request = navigationAction.request;
526544
NSURL* url = request.URL;
527545
NSString* scheme = url.scheme;
528-
546+
529547
BOOL isJSNavigation = [scheme isEqualToString:RCTJSNavigationScheme];
530-
548+
531549
// handle mailto and tel schemes
532550
if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"]) {
533551
if ([app canOpenURL:url]) {
@@ -536,7 +554,7 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
536554
return;
537555
}
538556
}
539-
557+
540558
// skip this for the JS Navigation handler
541559
if (!isJSNavigation && _onShouldStartLoadWithRequest) {
542560
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
@@ -550,7 +568,7 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
550568
return decisionHandler(WKNavigationActionPolicyCancel);
551569
}
552570
}
553-
571+
554572
if (_onLoadingStart) {
555573
// We have this check to filter out iframe requests and whatnot
556574
BOOL isTopFrame = [url isEqual:request.mainDocumentURL];
@@ -563,7 +581,7 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
563581
_onLoadingStart(event);
564582
}
565583
}
566-
584+
567585
if (isJSNavigation) {
568586
decisionHandler(WKNavigationActionPolicyCancel);
569587
}
@@ -582,7 +600,7 @@ - (void)webView:(__unused WKWebView *)webView didFailProvisionalNavigation:(__un
582600
// http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os
583601
return;
584602
}
585-
603+
586604
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
587605
[event addEntriesFromDictionary:@{
588606
@"domain": error.domain,
@@ -605,7 +623,7 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(__unused WKNavigation
605623

606624
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
607625
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
608-
626+
609627
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Close", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
610628
completionHandler();
611629
}]];
@@ -614,7 +632,7 @@ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSStrin
614632
}
615633

616634
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
617-
635+
618636
// TODO We have to think message to confirm "YES"
619637
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
620638
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
@@ -628,17 +646,17 @@ - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSStr
628646
}
629647

630648
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler {
631-
649+
632650
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:nil preferredStyle:UIAlertControllerStyleAlert];
633651
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
634652
textField.text = defaultText;
635653
}];
636-
654+
637655
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
638656
NSString *input = ((UITextField *)alertController.textFields.firstObject).text;
639657
completionHandler(input);
640658
}]];
641-
659+
642660
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
643661
completionHandler(nil);
644662
}]];

ios/RCTWKWebView/RCTWKWebViewManager.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ - (UIView *)view
6060
RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock)
6161
RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock)
6262
RCT_EXPORT_VIEW_PROPERTY(onProgress, RCTDirectEventBlock)
63+
RCT_EXPORT_VIEW_PROPERTY(onCanGoBackChange, RCTDirectEventBlock)
64+
RCT_EXPORT_VIEW_PROPERTY(onCanGoForwardChange, RCTDirectEventBlock)
6365
RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock)
6466
RCT_EXPORT_VIEW_PROPERTY(onScroll, RCTDirectEventBlock)
6567
RCT_EXPORT_VIEW_PROPERTY(hideKeyboardAccessoryView, BOOL)

0 commit comments

Comments
 (0)