From 1af17f164828b6d6fa0450af46baf945745363e7 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:22 -0700 Subject: [PATCH] Implement 'dataDetectorTypes' prop Summary: When text is rendered in `WKWebView` WebKit component, the component itself can detect things like phone numbers, flight numbers, links, etc. and render them with additional functionality. For example, when the text `apple.com` is detected, if the `link` data detector type is enabled, the web view will actually render a link that takes the user to the Apple home page. In this diff, I implement the `dataDetectorTypes` prop. The data detector types supported are: 1. phoneNumber 1. link 1. address 1. calendarEvent 1. trackingNumber 1. flightNumber 1. lookupSuggestion These enums are documented in the [[ https://developer.apple.com/documentation/webkit/wkdatadetectortypes | WKDataDetectorTypes docs ]]. Reviewed By: shergin Differential Revision: D6392546 fbshipit-source-id: 4dd373f0ac52f898163cd959eeef6672e55b42a6 --- Libraries/Components/WKWebView/WKWebView.ios.js | 2 ++ React/Base/RCTConvert.h | 2 ++ React/Base/RCTConvert.m | 12 ++++++++++++ React/Views/RCTWKWebView.h | 2 ++ React/Views/RCTWKWebView.m | 2 +- React/Views/RCTWKWebViewManager.m | 2 ++ React/Views/RCTWebViewManager.m | 4 ++-- 7 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Libraries/Components/WKWebView/WKWebView.ios.js b/Libraries/Components/WKWebView/WKWebView.ios.js index c13d463a32d4d6..ec4e635e28102a 100644 --- a/Libraries/Components/WKWebView/WKWebView.ios.js +++ b/Libraries/Components/WKWebView/WKWebView.ios.js @@ -18,12 +18,14 @@ const RCTWKWebView = requireNativeComponent('RCTWKWebView'); type RCTWKWebViewProps = { allowsInlineMediaPlayback?: boolean, mediaPlaybackRequiresUserAction?: boolean, + dataDetectorTypes?: boolean, }; class WKWebView extends React.Component { componentWillReceiveProps(nextProps: RCTWKWebViewProps) { this.showRedboxOnPropChanges(nextProps, 'allowsInlineMediaPlayback'); this.showRedboxOnPropChanges(nextProps, 'mediaPlaybackRequiresUserAction'); + this.showRedboxOnPropChanges(nextProps, 'dataDetectorTypes'); } showRedboxOnPropChanges(nextProps: RCTWKWebViewProps, propName: string) { diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 5780c5f5f676a8..1f66328ea76d18 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -15,6 +15,7 @@ #import #import #import +#import /** * This class provides a collection of conversion functions for mapping @@ -68,6 +69,7 @@ typedef NSURL RCTFileURL; + (UIReturnKeyType)UIReturnKeyType:(id)json; #if !TARGET_OS_TV + (UIDataDetectorTypes)UIDataDetectorTypes:(id)json; ++ (WKDataDetectorTypes)WKDataDetectorTypes:(id)json; #endif + (UIViewContentMode)UIViewContentMode:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 7528259fda00ad..90335e9894a338 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -361,6 +361,18 @@ + (NSLocale *)NSLocale:(id)json @"none": @(UIDataDetectorTypeNone), @"all": @(UIDataDetectorTypeAll), }), UIDataDetectorTypePhoneNumber, unsignedLongLongValue) + +RCT_MULTI_ENUM_CONVERTER(WKDataDetectorTypes, (@{ + @"phoneNumber": @(WKDataDetectorTypePhoneNumber), + @"link": @(WKDataDetectorTypeLink), + @"address": @(WKDataDetectorTypeAddress), + @"calendarEvent": @(WKDataDetectorTypeCalendarEvent), + @"trackingNumber": @(WKDataDetectorTypeTrackingNumber), + @"flightNumber": @(WKDataDetectorTypeFlightNumber), + @"lookupSuggestion": @(WKDataDetectorTypeLookupSuggestion), + @"none": @(WKDataDetectorTypeNone), + @"all": @(WKDataDetectorTypeAll), + }), WKDataDetectorTypePhoneNumber, unsignedLongLongValue) #endif RCT_ENUM_CONVERTER(UIKeyboardAppearance, (@{ diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 9b12d793d0c2b3..e9143033c7d0a3 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -8,6 +8,7 @@ */ #import +#import @class RCTWKWebView; @@ -30,6 +31,7 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, assign) BOOL allowsInlineMediaPlayback; @property (nonatomic, assign) BOOL bounces; @property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; +@property (nonatomic, assign) WKDataDetectorTypes dataDetectorTypes; - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index e6c2251b70fd8c..8cb16175f13ca3 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -1,5 +1,4 @@ #import "RCTWKWebView.h" -#import #import #import "RCTAutoInsetsProtocol.h" @@ -43,6 +42,7 @@ - (void)didMoveToWindow wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction ? WKAudiovisualMediaTypeAll : WKAudiovisualMediaTypeNone; + wkWebViewConfig.dataDetectorTypes = _dataDetectorTypes; _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; _webView.scrollView.delegate = self; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 5f6be7e9aeed57..b3b0f0b43cbed8 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -29,6 +29,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL) +RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes) + /** * Expose methods to enable messaging the webview. */ diff --git a/React/Views/RCTWebViewManager.m b/React/Views/RCTWebViewManager.m index 8f4ef9b0f4f793..3e7d0317b6dd2a 100644 --- a/React/Views/RCTWebViewManager.m +++ b/React/Views/RCTWebViewManager.m @@ -63,8 +63,8 @@ - (UIView *)view RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag) { - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - id view = viewRegistry[reactTag]; + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWebView *view = viewRegistry[reactTag]; if (![view isKindOfClass:[RCTWebView class]]) { RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); } else {