diff --git a/.gitignore b/.gitignore index fd4f2b06..bce24eb4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ node_modules .DS_Store + +.tags +.tags1 diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..b4d80f55 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +react-native-webview-bridge \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 00000000..97626ba4 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..cdc7de13 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + CSS + + + + + CoffeeScript + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..d31bbad0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/react-native-webview-bridge.iml b/.idea/react-native-webview-bridge.iml new file mode 100644 index 00000000..579af63c --- /dev/null +++ b/.idea/react-native-webview-bridge.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 00000000..015ebec3 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1476002628408 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index dfec22af..8b6e71a1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,22 +1,22 @@ buildscript { - repositories { - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - } +// repositories { +// jcenter() +// } +// +// dependencies { +// classpath 'com.android.tools.build:gradle:3.5.0' +// } } apply plugin: 'com.android.library' android { - compileSdkVersion 23 - buildToolsVersion "23.0.1" + compileSdkVersion 34 + buildToolsVersion "34.0.0" defaultConfig { - minSdkVersion 16 - targetSdkVersion 23 + minSdkVersion 23 + targetSdkVersion 34 versionCode 1 versionName "1.0" } @@ -30,5 +30,6 @@ repositories { } dependencies { - compile 'com.facebook.react:react-native:0.19.+' + api 'com.facebook.react:react-native:+' + implementation project(path: ':react-native-webview') } diff --git a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/JavascriptBridge.java b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/JavascriptBridge.java index 2ad37116..e21901d7 100644 --- a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/JavascriptBridge.java +++ b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/JavascriptBridge.java @@ -26,4 +26,4 @@ public void send(String message) { "topChange", event); } -} \ No newline at end of file +} diff --git a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java index c1250163..0777bb66 100644 --- a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java +++ b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java @@ -4,15 +4,15 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.views.webview.ReactWebViewManager; import com.facebook.react.uimanager.annotations.ReactProp; +import com.reactnativecommunity.webview.RNCWebViewManager; import java.util.ArrayList; import java.util.Map; import javax.annotation.Nullable; -public class WebViewBridgeManager extends ReactWebViewManager { +public class WebViewBridgeManager extends RNCWebViewManager { private static final String REACT_CLASS = "RCTWebViewBridge"; public static final int COMMAND_SEND_TO_BRIDGE = 101; @@ -75,4 +75,4 @@ public void setAllowFileAccessFromFileURLs(WebView root, boolean allows) { public void setAllowUniversalAccessFromFileURLs(WebView root, boolean allows) { root.getSettings().setAllowUniversalAccessFromFileURLs(allows); } -} \ No newline at end of file +} diff --git a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java index 1e189c4d..5cb0a4ef 100644 --- a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java +++ b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java @@ -23,7 +23,7 @@ public List createViewManagers(ReactApplicationContext reactApplica ); } - @Override + //@Override public List> createJSModules() { return Arrays.asList(); } diff --git a/ios/RCTWebViewBridge.h b/ios/RCTWebViewBridge.h index c7d34222..a6629ac3 100644 --- a/ios/RCTWebViewBridge.h +++ b/ios/RCTWebViewBridge.h @@ -10,8 +10,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +#if __has_include() #import - +#else +#import "RCTView.h" +#endif + @class RCTWebViewBridge; /** @@ -44,5 +48,7 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request - (void)goBack; - (void)reload; - (void)sendToBridge:(NSString *)message; +- (NSString*) getElementHTML:(NSString*)elementId; +- (NSString*) getSelectedHTML; @end diff --git a/ios/RCTWebViewBridge.m b/ios/RCTWebViewBridge.m index 86ddabc4..5d859ae6 100644 --- a/ios/RCTWebViewBridge.m +++ b/ios/RCTWebViewBridge.m @@ -13,6 +13,8 @@ #import "RCTWebViewBridge.h" #import +#import +#import "WKWebView+SynchronousEvaluateJavaScript.h" #import #import @@ -28,7 +30,7 @@ #define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding] //we don'e need this one since it has been defined in RCTWebView.m -//NSString *const RCTJSNavigationScheme = @"react-js-navigation"; +NSString *const RCTJSNavigationScheme = @"react-js-navigation"; NSString *const RCTWebViewBridgeSchema = @"wvb"; // runtime trick to remove UIWebview keyboard default toolbar @@ -41,7 +43,7 @@ -(id)inputAccessoryView } @end -@interface RCTWebViewBridge () +@interface RCTWebViewBridge () @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; @@ -53,7 +55,7 @@ @interface RCTWebViewBridge () @implementation RCTWebViewBridge { - UIWebView *_webView; + WKWebView *_webView; NSString *_injectedJavaScript; } @@ -63,9 +65,10 @@ - (instancetype)initWithFrame:(CGRect)frame super.backgroundColor = [UIColor clearColor]; _automaticallyAdjustContentInsets = YES; _contentInset = UIEdgeInsetsZero; - _webView = [[UIWebView alloc] initWithFrame:self.bounds]; - _webView.delegate = self; - _webView.mediaPlaybackRequiresUserAction = NO; + WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init]; + _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration:theConfiguration]; + [_webView setNavigationDelegate:self]; +// _webView.mediaPlaybackRequiresUserAction = NO; [self addSubview:_webView]; } return self; @@ -88,6 +91,18 @@ - (void)reload [_webView reload]; } +- (NSString*) getElementHTML:(NSString*)elementId +{ + NSString* JSString = [NSString stringWithFormat:@"document.getElementById(\"%@\").innerHTML",elementId]; + return [_webView stringByEvaluatingJavaScriptFromString:JSString]; +} + +- (NSString*) getSelectedHTML { + NSString* JSString = [NSString stringWithFormat:@"document.getSelection()"]; + NSLog(@"selectedHTML is: %@",JSString); + return [_webView stringByEvaluatingJavaScriptFromString:JSString]; +} + - (void)sendToBridge:(NSString *)message { //we are warpping the send message in a function to make sure that if @@ -109,7 +124,7 @@ - (void)sendToBridge:(NSString *)message - (NSURL *)URL { - return _webView.request.URL; + return _webView.URL; } - (void)setSource:(NSDictionary *)source @@ -130,7 +145,7 @@ - (void)setSource:(NSDictionary *)source // passing the redirect urls back here, so we ignore them if trying to load // the same url. We'll expose a call to 'reload' to allow a user to load // the existing page. - if ([request.URL isEqual:_webView.request.URL]) { + if ([request.URL isEqual:_webView.URL]) { return; } if (!request.URL) { @@ -171,7 +186,7 @@ - (UIColor *)backgroundColor - (NSMutableDictionary *)baseEvent { NSMutableDictionary *event = [[NSMutableDictionary alloc] initWithDictionary:@{ - @"url": _webView.request.URL.absoluteString ?: @"", + @"url": _webView.URL.absoluteString ?: @"", @"loading" : @(_webView.loading), @"title": [_webView stringByEvaluatingJavaScriptFromString:@"document.title"], @"canGoBack": @(_webView.canGoBack), @@ -196,7 +211,7 @@ -(void)setHideKeyboardAccessoryView:(BOOL)hideKeyboardAccessoryView UIView* subview; for (UIView* view in _webView.scrollView.subviews) { - if([[view.class description] hasPrefix:@"UIWeb"]) + if([[view.class description] hasPrefix:@"WK"]) subview = view; } @@ -219,98 +234,211 @@ -(void)setHideKeyboardAccessoryView:(BOOL)hideKeyboardAccessoryView object_setClass(subview, newClass); } -#pragma mark - UIWebViewDelegate methods - -- (BOOL)webView:(__unused UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request - navigationType:(UIWebViewNavigationType)navigationType +#pragma mark - WKNavigationDelegate methods +- (void)webView:(WKWebView *)webView + decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction + decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { - BOOL isJSNavigation = [request.URL.scheme isEqualToString:RCTJSNavigationScheme]; + BOOL isJSNavigation = [navigationAction.request.URL.scheme isEqualToString:RCTJSNavigationScheme]; - if (!isJSNavigation && [request.URL.scheme isEqualToString:RCTWebViewBridgeSchema]) { - NSString* message = [webView stringByEvaluatingJavaScriptFromString:@"WebViewBridge.__fetch__()"]; + if (!isJSNavigation && [navigationAction.request.URL.scheme isEqualToString:RCTWebViewBridgeSchema]) { + NSString* message = [webView stringByEvaluatingJavaScriptFromString:@"WebViewBridge.__fetch__()"]; - NSMutableDictionary *onBridgeMessageEvent = [[NSMutableDictionary alloc] initWithDictionary:@{ - @"messages": [self stringArrayJsonToArray: message] - }]; + NSMutableDictionary *onBridgeMessageEvent = [[NSMutableDictionary alloc] initWithDictionary:@{ + @"messages": [self stringArrayJsonToArray: message] + }]; - _onBridgeMessage(onBridgeMessageEvent); + _onBridgeMessage(onBridgeMessageEvent); - isJSNavigation = YES; - } + isJSNavigation = YES; + } - // skip this for the JS Navigation handler - if (!isJSNavigation && _onShouldStartLoadWithRequest) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"url": (request.URL).absoluteString, - @"navigationType": @(navigationType) - }]; - if (![self.delegate webView:self - shouldStartLoadForRequest:event - withCallback:_onShouldStartLoadWithRequest]) { - return NO; + // skip this for the JS Navigation handler + if (!isJSNavigation && _onShouldStartLoadWithRequest) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{ + @"url": (navigationAction.request.URL).absoluteString, + @"navigationType": @(navigationAction.navigationType) + }]; + if (![self.delegate webView:self + shouldStartLoadForRequest:event + withCallback:_onShouldStartLoadWithRequest]) { + decisionHandler(WKNavigationActionPolicyCancel); + return; + } } - } - if (_onLoadingStart) { - // We have this check to filter out iframe requests and whatnot - BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL]; - if (isTopFrame) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"url": (request.URL).absoluteString, - @"navigationType": @(navigationType) - }]; - _onLoadingStart(event); + if (_onLoadingStart) { + // We have this check to filter out iframe requests and whatnot + BOOL isTopFrame = [navigationAction.request.URL isEqual:navigationAction.request.mainDocumentURL]; + if (isTopFrame) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{ + @"url": (navigationAction.request.URL).absoluteString, + @"navigationType": @(navigationAction.navigationType) + }]; + _onLoadingStart(event); + } } - } - // JS Navigation handler - return !isJSNavigation; + // JS Navigation handler + decisionHandler(isJSNavigation ? WKNavigationActionPolicyCancel : WKNavigationActionPolicyAllow); } -- (void)webView:(__unused UIWebView *)webView didFailLoadWithError:(NSError *)error +//- (BOOL)webView:(__unused UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request +// navigationType:(UIWebViewNavigationType)navigationType +//{ +// BOOL isJSNavigation = [request.URL.scheme isEqualToString:RCTJSNavigationScheme]; +// +// if (!isJSNavigation && [request.URL.scheme isEqualToString:RCTWebViewBridgeSchema]) { +// NSString* message = [webView stringByEvaluatingJavaScriptFromString:@"WebViewBridge.__fetch__()"]; +// +// NSMutableDictionary *onBridgeMessageEvent = [[NSMutableDictionary alloc] initWithDictionary:@{ +// @"messages": [self stringArrayJsonToArray: message] +// }]; +// +// _onBridgeMessage(onBridgeMessageEvent); +// +// isJSNavigation = YES; +// } +// +// // skip this for the JS Navigation handler +// if (!isJSNavigation && _onShouldStartLoadWithRequest) { +// NSMutableDictionary *event = [self baseEvent]; +// [event addEntriesFromDictionary: @{ +// @"url": (request.URL).absoluteString, +// @"navigationType": @(navigationType) +// }]; +// if (![self.delegate webView:self +// shouldStartLoadForRequest:event +// withCallback:_onShouldStartLoadWithRequest]) { +// return NO; +// } +// } +// +// if (_onLoadingStart) { +// // We have this check to filter out iframe requests and whatnot +// BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL]; +// if (isTopFrame) { +// NSMutableDictionary *event = [self baseEvent]; +// [event addEntriesFromDictionary: @{ +// @"url": (request.URL).absoluteString, +// @"navigationType": @(navigationType) +// }]; +// _onLoadingStart(event); +// } +// } +// +// // JS Navigation handler +// return !isJSNavigation; +//} +// + +- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { - if (_onLoadingError) { - if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { - // NSURLErrorCancelled is reported when a page has a redirect OR if you load - // a new URL in the WebView before the previous one came back. We can just - // ignore these since they aren't real errors. - // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os - return; + if (_onLoadingError) { + if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { + // NSURLErrorCancelled is reported when a page has a redirect OR if you load + // a new URL in the WebView before the previous one came back. We can just + // ignore these since they aren't real errors. + // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os + return; + } + + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary:@{ + @"domain": error.domain, + @"code": @(error.code), + @"description": error.localizedDescription, + }]; + _onLoadingError(event); } +} - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary:@{ - @"domain": error.domain, - @"code": @(error.code), - @"description": error.localizedDescription, - }]; - _onLoadingError(event); - } +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error +{ + if (_onLoadingError) { + if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { + // NSURLErrorCancelled is reported when a page has a redirect OR if you load + // a new URL in the WebView before the previous one came back. We can just + // ignore these since they aren't real errors. + // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os + return; + } + + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary:@{ + @"domain": error.domain, + @"code": @(error.code), + @"description": error.localizedDescription, + }]; + _onLoadingError(event); + } } -- (void)webViewDidFinishLoad:(UIWebView *)webView +//- (void)webView:(__unused UIWebView *)webView didFailLoadWithError:(NSError *)error +//{ +// if (_onLoadingError) { +// if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { +// // NSURLErrorCancelled is reported when a page has a redirect OR if you load +// // a new URL in the WebView before the previous one came back. We can just +// // ignore these since they aren't real errors. +// // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os +// return; +// } +// +// NSMutableDictionary *event = [self baseEvent]; +// [event addEntriesFromDictionary:@{ +// @"domain": error.domain, +// @"code": @(error.code), +// @"description": error.localizedDescription, +// }]; +// _onLoadingError(event); +// } +//} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { - //injecting WebViewBridge Script - NSString *webViewBridgeScriptContent = [self webViewBridgeScript]; - [webView stringByEvaluatingJavaScriptFromString:webViewBridgeScriptContent]; - ////////////////////////////////////////////////////////////////////////////// + //injecting WebViewBridge Script + NSString *webViewBridgeScriptContent = [self webViewBridgeScript]; + [webView stringByEvaluatingJavaScriptFromString:webViewBridgeScriptContent]; + ////////////////////////////////////////////////////////////////////////////// - if (_injectedJavaScript != nil) { - NSString *jsEvaluationValue = [webView stringByEvaluatingJavaScriptFromString:_injectedJavaScript]; + if (_injectedJavaScript != nil) { + NSString *jsEvaluationValue = [webView stringByEvaluatingJavaScriptFromString:_injectedJavaScript]; - NSMutableDictionary *event = [self baseEvent]; - event[@"jsEvaluationValue"] = jsEvaluationValue; + NSMutableDictionary *event = [self baseEvent]; + event[@"jsEvaluationValue"] = jsEvaluationValue; - _onLoadingFinish(event); - } - // we only need the final 'finishLoad' call so only fire the event when we're actually done loading. - else if (_onLoadingFinish && !webView.loading && ![webView.request.URL.absoluteString isEqualToString:@"about:blank"]) { - _onLoadingFinish([self baseEvent]); - } + _onLoadingFinish(event); + } + // we only need the final 'finishLoad' call so only fire the event when we're actually done loading. + else if (_onLoadingFinish && !webView.loading && ![webView.URL.absoluteString isEqualToString:@"about:blank"]) { + _onLoadingFinish([self baseEvent]); + } } +//- (void)webViewDidFinishLoad:(UIWebView *)webView +//{ +// //injecting WebViewBridge Script +// NSString *webViewBridgeScriptContent = [self webViewBridgeScript]; +// [webView stringByEvaluatingJavaScriptFromString:webViewBridgeScriptContent]; +// ////////////////////////////////////////////////////////////////////////////// +// +// if (_injectedJavaScript != nil) { +// NSString *jsEvaluationValue = [webView stringByEvaluatingJavaScriptFromString:_injectedJavaScript]; +// +// NSMutableDictionary *event = [self baseEvent]; +// event[@"jsEvaluationValue"] = jsEvaluationValue; +// +// _onLoadingFinish(event); +// } +// // we only need the final 'finishLoad' call so only fire the event when we're actually done loading. +// else if (_onLoadingFinish && !webView.loading && ![webView.request.URL.absoluteString isEqualToString:@"about:blank"]) { +// _onLoadingFinish([self baseEvent]); +// } +//} + - (NSArray*)stringArrayJsonToArray:(NSString *)message { return [NSJSONSerialization JSONObjectWithData:[message dataUsingEncoding:NSUTF8StringEncoding] diff --git a/ios/RCTWebViewBridgeManager.m b/ios/RCTWebViewBridgeManager.m index 218cca0e..2c5796c7 100644 --- a/ios/RCTWebViewBridgeManager.m +++ b/ios/RCTWebViewBridgeManager.m @@ -11,11 +11,25 @@ */ #import "RCTWebViewBridgeManager.h" +#import "RCTWebViewBridge.h" +#if __has_include() #import +#else +#import "RCTBridge.h" +#endif + +#if __has_include() #import -#import "RCTWebViewBridge.h" +#else +#import "RCTUIManager.h" +#endif + +#if __has_include() +#import +#else #import "UIView+React.h" +#endif @interface RCTWebViewBridgeManager () @@ -49,8 +63,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock) RCT_REMAP_VIEW_PROPERTY(allowsInlineMediaPlayback, _webView.allowsInlineMediaPlayback, BOOL) -RCT_REMAP_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, _webView.mediaPlaybackRequiresUserAction, BOOL) RCT_EXPORT_VIEW_PROPERTY(onBridgeMessage, RCTDirectEventBlock) +//RCT_REMAP_VIEW_PROPERTY(keyboardDisplayRequiresUserAction, _webView.keyboardDisplayRequiresUserAction, BOOL) - (NSDictionary *)constantsToExport { @@ -87,7 +101,7 @@ + (BOOL)requiresMainQueueSetup RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebViewBridge *view = viewRegistry[reactTag]; + RCTWebViewBridge* view = viewRegistry[reactTag]; if (![view isKindOfClass:[RCTWebViewBridge class]]) { RCTLogError(@"Invalid view returned from registry, expecting RCTWebViewBridge, got: %@", view); } else { @@ -108,6 +122,34 @@ + (BOOL)requiresMainQueueSetup }]; } +RCT_EXPORT_METHOD(getElementHTML:(nonnull NSNumber *)reactTag :(NSString*)elementId :(RCTResponseSenderBlock)callback) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWebViewBridge *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWebViewBridge class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebViewBridge, got: %@", view); + } else { + NSString* html = [view getElementHTML:elementId]; + NSLog(@"Editor HTML is %@", html); + callback(@[[NSNull null], html]); + } + }]; +} + +RCT_EXPORT_METHOD(getSelectedHTML:(nonnull NSNumber *)reactTag :(NSString*)elementId :(RCTResponseSenderBlock)callback) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWebViewBridge *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWebViewBridge class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebViewBridge, got: %@", view); + } else { + NSString* html = [view getSelectedHTML]; + NSLog(@"Selected HTML is %@", html); + callback(@[[NSNull null], html]); + } + }]; +} + RCT_EXPORT_METHOD(sendToBridge:(nonnull NSNumber *)reactTag value:(NSString*)message) { @@ -139,8 +181,8 @@ - (BOOL)webView:(__unused RCTWebViewBridge *)webView _shouldStartLoadLock = nil; return returnValue; } else { - RCTLogWarn(@"Did not receive response to shouldStartLoad in time, defaulting to YES"); - return YES; + RCTLogWarn(@"Did not receive response to shouldStartLoad in time, defaulting to NO"); + return NO; } } diff --git a/ios/React-Native-Webview-Bridge.xcodeproj/project.pbxproj b/ios/React-Native-Webview-Bridge.xcodeproj/project.pbxproj index 8f5454de..461379e9 100644 --- a/ios/React-Native-Webview-Bridge.xcodeproj/project.pbxproj +++ b/ios/React-Native-Webview-Bridge.xcodeproj/project.pbxproj @@ -9,13 +9,14 @@ /* Begin PBXBuildFile section */ 4114DC5C1C187CCB003CD988 /* RCTWebViewBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 4114DC591C187CCB003CD988 /* RCTWebViewBridge.m */; }; 4114DC5D1C187CCB003CD988 /* RCTWebViewBridgeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4114DC5B1C187CCB003CD988 /* RCTWebViewBridgeManager.m */; }; + D822A676238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.m in Sources */ = {isa = PBXBuildFile; fileRef = D822A675238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 4114DC4A1C187C3A003CD988 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; + dstPath = "include/$(TARGET_NAME)"; dstSubfolderSpec = 16; files = ( ); @@ -29,7 +30,8 @@ 4114DC591C187CCB003CD988 /* RCTWebViewBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWebViewBridge.m; sourceTree = SOURCE_ROOT; }; 4114DC5A1C187CCB003CD988 /* RCTWebViewBridgeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWebViewBridgeManager.h; sourceTree = SOURCE_ROOT; }; 4114DC5B1C187CCB003CD988 /* RCTWebViewBridgeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWebViewBridgeManager.m; sourceTree = SOURCE_ROOT; }; - 4114DC5F1C187CE4003CD988 /* webviewbridge.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = webviewbridge.js; sourceTree = ""; }; + D822A674238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WKWebView+SynchronousEvaluateJavaScript.h"; sourceTree = SOURCE_ROOT; }; + D822A675238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "WKWebView+SynchronousEvaluateJavaScript.m"; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -47,7 +49,6 @@ isa = PBXGroup; children = ( 4114DC4E1C187C3A003CD988 /* React-Native-Webview-Bridge */, - 4114DC5E1C187CE4003CD988 /* scripts */, 4114DC4D1C187C3A003CD988 /* Products */, ); sourceTree = ""; @@ -67,19 +68,12 @@ 4114DC591C187CCB003CD988 /* RCTWebViewBridge.m */, 4114DC5A1C187CCB003CD988 /* RCTWebViewBridgeManager.h */, 4114DC5B1C187CCB003CD988 /* RCTWebViewBridgeManager.m */, + D822A674238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.h */, + D822A675238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.m */, ); path = "React-Native-Webview-Bridge"; sourceTree = ""; }; - 4114DC5E1C187CE4003CD988 /* scripts */ = { - isa = PBXGroup; - children = ( - 4114DC5F1C187CE4003CD988 /* webviewbridge.js */, - ); - name = scripts; - path = ../scripts; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -119,6 +113,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 4114DC431C187C3A003CD988; @@ -136,6 +131,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D822A676238DABDC001CCF6E /* WKWebView+SynchronousEvaluateJavaScript.m in Sources */, 4114DC5D1C187CCB003CD988 /* RCTWebViewBridgeManager.m in Sources */, 4114DC5C1C187CCB003CD988 /* RCTWebViewBridge.m in Sources */, ); diff --git a/ios/React-Native-Webview-Bridge.xcodeproj/xcuserdata/ali.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/React-Native-Webview-Bridge.xcodeproj/xcuserdata/ali.xcuserdatad/xcschemes/xcschememanagement.plist index 2f988c46..d69df63b 100644 --- a/ios/React-Native-Webview-Bridge.xcodeproj/xcuserdata/ali.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ios/React-Native-Webview-Bridge.xcodeproj/xcuserdata/ali.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,6 +9,11 @@ orderHint 0 + react-native-webview-bridge.xcscheme + + orderHint + 1 + SuppressBuildableAutocreation diff --git a/ios/WKWebView+SynchronousEvaluateJavaScript.h b/ios/WKWebView+SynchronousEvaluateJavaScript.h new file mode 100644 index 00000000..47860265 --- /dev/null +++ b/ios/WKWebView+SynchronousEvaluateJavaScript.h @@ -0,0 +1,14 @@ +// +// WKWebView+ SynchronousEvaluateJavaScript.h +// React-Native-Webview-Bridge +// +// Created by Guy Eldar on 26/11/2019. +// Copyright © 2019 alinz. All rights reserved. +// + +#import +#import + +@interface WKWebView(SynchronousEvaluateJavaScript) +- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; +@end diff --git a/ios/WKWebView+SynchronousEvaluateJavaScript.m b/ios/WKWebView+SynchronousEvaluateJavaScript.m new file mode 100644 index 00000000..ad327d3a --- /dev/null +++ b/ios/WKWebView+SynchronousEvaluateJavaScript.m @@ -0,0 +1,35 @@ +// +// WKWebView+ SynchronousEvaluateJavaScript.m +// React-Native-Webview-Bridge +// +// Created by Guy Eldar on 26/11/2019. +// Copyright © 2019 alinz. All rights reserved. +// + +#import "WKWebView+SynchronousEvaluateJavaScript.h" + +@implementation WKWebView(SynchronousEvaluateJavaScript) +- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script +{ + __block NSString *resultString = nil; + __block BOOL finished = NO; + + [self evaluateJavaScript:script completionHandler:^(id result, NSError *error) { + if (error == nil) { + if (result != nil) { + resultString = [NSString stringWithFormat:@"%@", result]; + } + } else { + NSLog(@"evaluateJavaScript error : %@", error.localizedDescription); + } + finished = YES; + }]; + + while (!finished) + { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; + } + + return resultString; +} +@end diff --git a/package.json b/package.json index b3b9c04c..611a0cf2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-webview-bridge", - "version": "0.40.2", + "version": "0.62.5", "description": "React Native WebView Javascript Bridge", "main": "webview-bridge", "directories": { @@ -33,9 +33,7 @@ "create-react-class": "^15.6.0", "invariant": "^2.2.2", "keymirror": "0.1.1", - "prop-types": "^15.5.10" - }, - "peerDependencies": { - "react-native-webview": "^7.5.2" + "prop-types": "^15.5.10", + "react-native-webview": "^11.0.0" } } diff --git a/react-native-webview-bridge.podspec b/react-native-webview-bridge.podspec index ade1912a..7f1b77a4 100644 --- a/react-native-webview-bridge.podspec +++ b/react-native-webview-bridge.podspec @@ -1,17 +1,17 @@ require 'json' -version = JSON.parse(File.read('package.json'))["version"] +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) Pod::Spec.new do |s| s.name = "react-native-webview-bridge" - s.version = version + s.version = package['version'] s.homepage = "https://github.com/alinz/react-native-webview-bridge" s.summary = "A webview bridge for react-native" s.license = "MIT" s.author = { "alinz" => "a.najafizadeh@gmail.com" } s.ios.deployment_target = '9.0' s.tvos.deployment_target = '9.0' - s.source = { :git => "https://github.com/alinz/react-native-webview-bridge", :tag => "#{s.version}" } + s.source = { :git => "https://github.com/HoneyBook/react-native-webview-bridge"} s.source_files = 'ios/*.{h,m}' s.preserve_paths = "**/*.js" s.frameworks = 'UIKit', 'QuartzCore', 'Foundation' diff --git a/scripts/webviewbridge.js b/scripts/WebViewBridge.js similarity index 100% rename from scripts/webviewbridge.js rename to scripts/WebViewBridge.js diff --git a/webview-bridge/index.android.js b/webview-bridge/index.android.js index b98cfc44..641f4f01 100644 --- a/webview-bridge/index.android.js +++ b/webview-bridge/index.android.js @@ -21,15 +21,13 @@ var invariant = require('invariant'); var keyMirror = require('keymirror'); var resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource'); -var WebView = require('react-native-webview'); +//var WebView = require('react-native-webview'); var { ReactNativeViewAttributes, UIManager, - EdgeInsetsPropType, StyleSheet, Text, View, - ViewPropTypes, requireNativeComponent, DeviceEventEmitter, NativeModules: { @@ -69,7 +67,7 @@ var WebViewBridge = createReactClass({ }; }, - + componentDidMount: function() { DeviceEventEmitter.addListener("webViewBridgeMessage", (body) => { const { onBridgeMessage } = this.props; @@ -87,21 +85,21 @@ var WebViewBridge = createReactClass({ render: function() { var otherView = null; - if (this.state.viewState === WebViewBridgeState.LOADING) { + if (this.state.viewState === WebViewBridgeState.LOADING) { otherView = this.props.renderLoading && this.props.renderLoading(); } else if (this.state.viewState === WebViewBridgeState.ERROR) { var errorEvent = this.state.lastErrorEvent; otherView = this.props.renderError && this.props.renderError( - errorEvent.domain, - errorEvent.code, - errorEvent.description); + errorEvent.domain, + errorEvent.code, + errorEvent.description); } else if (this.state.viewState !== WebViewBridgeState.IDLE) { console.error('RCTWebViewBridge invalid state encountered: ' + this.state.loading); } var webViewStyles = [styles.container, this.props.style]; if (this.state.viewState === WebViewBridgeState.LOADING || - this.state.viewState === WebViewBridgeState.ERROR) { + this.state.viewState === WebViewBridgeState.ERROR) { // if we're in either LOADING or ERROR states, don't show the webView webViewStyles.push(styles.hidden); } @@ -119,24 +117,24 @@ var WebViewBridge = createReactClass({ let {source, ...props} = {...this.props}; var webView = - ; + ; return ( - - {webView} - {otherView} - + + {webView} + {otherView} + ); }, @@ -148,33 +146,33 @@ var WebViewBridge = createReactClass({ goForward: function() { UIManager.dispatchViewManagerCommand( - this.getWebViewBridgeHandle(), - UIManager.RCTWebViewBridge.Commands.goForward, - null + this.getWebViewBridgeHandle(), + UIManager.RCTWebViewBridge.Commands.goForward, + null ); }, goBack: function() { UIManager.dispatchViewManagerCommand( - this.getWebViewBridgeHandle(), - UIManager.RCTWebViewBridge.Commands.goBack, - null + this.getWebViewBridgeHandle(), + UIManager.RCTWebViewBridge.Commands.goBack, + null ); }, reload: function() { UIManager.dispatchViewManagerCommand( - this.getWebViewBridgeHandle(), - UIManager.RCTWebViewBridge.Commands.reload, - null + this.getWebViewBridgeHandle(), + UIManager.RCTWebViewBridge.Commands.reload, + null ); }, sendToBridge: function (message: string) { UIManager.dispatchViewManagerCommand( - this.getWebViewBridgeHandle(), - UIManager.RCTWebViewBridge.Commands.sendToBridge, - [message] + this.getWebViewBridgeHandle(), + UIManager.RCTWebViewBridge.Commands.sendToBridge, + [message] ); }, diff --git a/webview-bridge/index.ios.js b/webview-bridge/index.ios.js index 0d147bd3..7a99214b 100644 --- a/webview-bridge/index.ios.js +++ b/webview-bridge/index.ios.js @@ -22,14 +22,13 @@ var invariant = require('invariant'); var keyMirror = require('keymirror'); var resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource'); -var WebView = require('react-native-webview'); +//import { WebView } from "react-native-webview"; + var { ActivityIndicator, - EdgeInsetsPropType, StyleSheet, Text, View, - ViewPropTypes, requireNativeComponent, UIManager, NativeModules: { @@ -99,7 +98,7 @@ var WebViewBridge = createReactClass({ }, propTypes: { - ...WebView.propTypes, +// ...WebView.propTypes, /** * Will be called once the message is being sent from webview @@ -235,6 +234,16 @@ var WebViewBridge = createReactClass({ WebViewBridgeManager.sendToBridge(this.getWebViewBridgeHandle(), message); }, + getElementHTML: function (elementId: string, callback) { + var html = WebViewBridgeManager.getElementHTML(this.getWebViewBridgeHandle(), elementId, callback); + console.log("html from editor is " + html); + }, + + getSelectedHTML: function (elementId: string, callback) { + var html = WebViewBridgeManager.getSelectedHTML(this.getWebViewBridgeHandle(), elementId, callback); + console.log("html from editor is " + html); + }, + /** * We return an event with a bunch of fields including: * url, title, loading, canGoBack, canGoForward diff --git a/yarn.lock b/yarn.lock index 846d6432..da54122c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,6 +24,11 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" +escape-string-regexp@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + fbjs@^0.8.16, fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" @@ -40,9 +45,10 @@ iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" +invariant@2.2.4, invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" @@ -96,13 +102,22 @@ prop-types@^15.5.10: loose-envify "^1.3.1" object-assign "^4.1.1" +react-native-webview@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-11.0.0.tgz#d667cbcc772e963fe88a4156290d25fe47ed43b0" + integrity sha512-gzID5ebCFVNkxreuabClymo6QkJbXCLEtiIUY9QAhxY58HsDUp8x0YzDVEROYyEJ4ghL71koAOeQRDNAgNnh1w== + dependencies: + escape-string-regexp "2.0.0" + invariant "2.2.4" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" ua-parser-js@^0.7.9: - version "0.7.17" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + version "0.7.33" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" + integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== whatwg-fetch@>=0.10.0: version "2.0.3"