From e697dff1d0a5b2cc97f123862b11e4e7c8db85e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Chmiela?= Date: Tue, 19 Mar 2019 15:42:47 +0100 Subject: [PATCH] chore(format): Android project formatting (#433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added an extremely simple `.editorconfig` I inferred from the main part of the project, then reformatted the codebase according to it. 🙂 --- android/.editorconfig | 6 + android/src/main/AndroidManifest.xml | 26 +- .../webview/RNCWebViewFileProvider.java | 2 +- .../webview/RNCWebViewManager.java | 636 +++++++++--------- .../webview/RNCWebViewModule.java | 216 +++--- .../webview/RNCWebViewPackage.java | 59 +- .../webview/events/TopLoadingErrorEvent.kt | 18 +- .../webview/events/TopLoadingFinishEvent.kt | 18 +- .../webview/events/TopLoadingProgressEvent.kt | 18 +- .../webview/events/TopLoadingStartEvent.kt | 18 +- .../webview/events/TopMessageEvent.kt | 22 +- .../TopShouldStartLoadWithRequestEvent.kt | 22 +- .../src/main/res/xml/file_provider_paths.xml | 6 +- 13 files changed, 529 insertions(+), 538 deletions(-) create mode 100644 android/.editorconfig diff --git a/android/.editorconfig b/android/.editorconfig new file mode 100644 index 0000000..8286f5f --- /dev/null +++ b/android/.editorconfig @@ -0,0 +1,6 @@ +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=false +indent_style=space +indent_size=2 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 2d72d6f..b8f945d 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,13 +1,15 @@ - - - - - - + + + + + + + diff --git a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewFileProvider.java b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewFileProvider.java index 0d7773d..8587b3f 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewFileProvider.java +++ b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewFileProvider.java @@ -4,7 +4,7 @@ import android.support.v4.content.FileProvider; /** * Providing a custom {@code FileProvider} prevents manifest {@code } name collisions. - * + *

* See https://developer.android.com/guide/topics/manifest/provider-element.html for details. */ public class RNCWebViewFileProvider extends FileProvider { diff --git a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java index 38b42b8..ac314d1 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java +++ b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java @@ -4,24 +4,6 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.DownloadManager; import android.content.Context; - -import com.facebook.react.uimanager.UIManagerModule; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Pattern; -import javax.annotation.Nullable; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import android.content.ActivityNotFoundException; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; @@ -43,7 +25,6 @@ import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; -import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactContext; @@ -52,67 +33,62 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.MapBuilder; -import com.facebook.react.common.ReactConstants; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.ContentSizeChangeEvent; import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.uimanager.events.RCTEventEmitter; import com.reactnativecommunity.webview.events.TopLoadingErrorEvent; import com.reactnativecommunity.webview.events.TopLoadingFinishEvent; +import com.reactnativecommunity.webview.events.TopLoadingProgressEvent; import com.reactnativecommunity.webview.events.TopLoadingStartEvent; import com.reactnativecommunity.webview.events.TopMessageEvent; -import com.reactnativecommunity.webview.events.TopLoadingProgressEvent; import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import javax.annotation.Nullable; + import org.json.JSONException; import org.json.JSONObject; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.annotation.Nullable; + /** * Manages instances of {@link WebView} - * + *

* Can accept following commands: - * - GO_BACK - * - GO_FORWARD - * - RELOAD - * - LOAD_URL - * + * - GO_BACK + * - GO_FORWARD + * - RELOAD + * - LOAD_URL + *

* {@link WebView} instances could emit following direct events: - * - topLoadingFinish - * - topLoadingStart - * - topLoadingStart - * - topLoadingProgress - * - topShouldStartLoadWithRequest - * + * - topLoadingFinish + * - topLoadingStart + * - topLoadingStart + * - topLoadingProgress + * - topShouldStartLoadWithRequest + *

* Each event will carry the following properties: - * - target - view's react tag - * - url - url set for the webview - * - loading - whether webview is in a loading state - * - title - title of the current page - * - canGoBack - boolean, whether there is anything on a history stack to go back - * - canGoForward - boolean, whether it is possible to request GO_FORWARD command + * - target - view's react tag + * - url - url set for the webview + * - loading - whether webview is in a loading state + * - title - title of the current page + * - canGoBack - boolean, whether there is anything on a history stack to go back + * - canGoForward - boolean, whether it is possible to request GO_FORWARD command */ @ReactModule(name = RNCWebViewManager.REACT_CLASS) public class RNCWebViewManager extends SimpleViewManager { - protected static final String REACT_CLASS = "RNCWebView"; - private RNCWebViewPackage aPackage; - - protected static final String HTML_ENCODING = "UTF-8"; - protected static final String HTML_MIME_TYPE = "text/html"; - protected static final String JAVASCRIPT_INTERFACE = "ReactNativeWebView"; - - protected static final String HTTP_METHOD_POST = "POST"; - public static final int COMMAND_GO_BACK = 1; public static final int COMMAND_GO_FORWARD = 2; public static final int COMMAND_RELOAD = 3; @@ -120,246 +96,16 @@ public class RNCWebViewManager extends SimpleViewManager { public static final int COMMAND_POST_MESSAGE = 5; public static final int COMMAND_INJECT_JAVASCRIPT = 6; public static final int COMMAND_LOAD_URL = 7; - + protected static final String REACT_CLASS = "RNCWebView"; + protected static final String HTML_ENCODING = "UTF-8"; + protected static final String HTML_MIME_TYPE = "text/html"; + protected static final String JAVASCRIPT_INTERFACE = "ReactNativeWebView"; + protected static final String HTTP_METHOD_POST = "POST"; // Use `webView.loadUrl("about:blank")` to reliably reset the view // state and release page resources (including any running JavaScript). protected static final String BLANK_URL = "about:blank"; - protected WebViewConfig mWebViewConfig; - - protected static class RNCWebViewClient extends WebViewClient { - - protected boolean mLastLoadFailed = false; - protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent; - - @Override - public void onPageFinished(WebView webView, String url) { - super.onPageFinished(webView, url); - - if (!mLastLoadFailed) { - RNCWebView reactWebView = (RNCWebView) webView; - - reactWebView.callInjectedJavaScript(); - - emitFinishEvent(webView, url); - } - } - - @Override - public void onPageStarted(WebView webView, String url, Bitmap favicon) { - super.onPageStarted(webView, url, favicon); - mLastLoadFailed = false; - - dispatchEvent( - webView, - new TopLoadingStartEvent( - webView.getId(), - createWebViewEvent(webView, url))); - } - - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - dispatchEvent( - view, - new TopShouldStartLoadWithRequestEvent( - view.getId(), - createWebViewEvent(view, url))); - return true; - } - - - @TargetApi(Build.VERSION_CODES.N) - @Override - public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - final String url = request.getUrl().toString(); - return this.shouldOverrideUrlLoading(view, url); - } - - @Override - public void onReceivedError( - WebView webView, - int errorCode, - String description, - String failingUrl) { - super.onReceivedError(webView, errorCode, description, failingUrl); - mLastLoadFailed = true; - - // In case of an error JS side expect to get a finish event first, and then get an error event - // Android WebView does it in the opposite way, so we need to simulate that behavior - emitFinishEvent(webView, failingUrl); - - WritableMap eventData = createWebViewEvent(webView, failingUrl); - eventData.putDouble("code", errorCode); - eventData.putString("description", description); - - dispatchEvent( - webView, - new TopLoadingErrorEvent(webView.getId(), eventData)); - } - - protected void emitFinishEvent(WebView webView, String url) { - dispatchEvent( - webView, - new TopLoadingFinishEvent( - webView.getId(), - createWebViewEvent(webView, url))); - } - - protected WritableMap createWebViewEvent(WebView webView, String url) { - WritableMap event = Arguments.createMap(); - event.putDouble("target", webView.getId()); - // Don't use webView.getUrl() here, the URL isn't updated to the new value yet in callbacks - // like onPageFinished - event.putString("url", url); - event.putBoolean("loading", !mLastLoadFailed && webView.getProgress() != 100); - event.putString("title", webView.getTitle()); - event.putBoolean("canGoBack", webView.canGoBack()); - event.putBoolean("canGoForward", webView.canGoForward()); - return event; - } - - public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) { - mUrlPrefixesForDefaultIntent = specialUrls; - } - } - - /** - * Subclass of {@link WebView} that implements {@link LifecycleEventListener} interface in order - * to call {@link WebView#destroy} on activity destroy event and also to clear the client - */ - protected static class RNCWebView extends WebView implements LifecycleEventListener { - protected @Nullable String injectedJS; - protected boolean messagingEnabled = false; - protected @Nullable RNCWebViewClient mRNCWebViewClient; - protected boolean sendContentSizeChangeEvents = false; - public void setSendContentSizeChangeEvents(boolean sendContentSizeChangeEvents) { - this.sendContentSizeChangeEvents = sendContentSizeChangeEvents; - } - - - protected class RNCWebViewBridge { - RNCWebView mContext; - - RNCWebViewBridge(RNCWebView c) { - mContext = c; - } - - /** - * This method is called whenever JavaScript running within the web view calls: - * - window[JAVASCRIPT_INTERFACE].postMessage - */ - @JavascriptInterface - public void postMessage(String message) { - mContext.onMessage(message); - } - } - - /** - * WebView must be created with an context of the current activity - * - * Activity Context is required for creation of dialogs internally by WebView - * Reactive Native needed for access to ReactNative internal system functionality - * - */ - public RNCWebView(ThemedReactContext reactContext) { - super(reactContext); - } - - @Override - public void onHostResume() { - // do nothing - } - - @Override - public void onHostPause() { - // do nothing - } - - @Override - public void onHostDestroy() { - cleanupCallbacksAndDestroy(); - } - - @Override - protected void onSizeChanged(int w, int h, int ow, int oh) { - super.onSizeChanged(w, h, ow, oh); - - if (sendContentSizeChangeEvents) { - dispatchEvent( - this, - new ContentSizeChangeEvent( - this.getId(), - w, - h - ) - ); - } - } - - @Override - public void setWebViewClient(WebViewClient client) { - super.setWebViewClient(client); - mRNCWebViewClient = (RNCWebViewClient)client; - } - - public @Nullable RNCWebViewClient getRNCWebViewClient() { - return mRNCWebViewClient; - } - - public void setInjectedJavaScript(@Nullable String js) { - injectedJS = js; - } - - protected RNCWebViewBridge createRNCWebViewBridge(RNCWebView webView) { - return new RNCWebViewBridge(webView); - } - - @SuppressLint("AddJavascriptInterface") - public void setMessagingEnabled(boolean enabled) { - if (messagingEnabled == enabled) { - return; - } - - messagingEnabled = enabled; - - if (enabled) { - addJavascriptInterface(createRNCWebViewBridge(this), JAVASCRIPT_INTERFACE); - } else { - removeJavascriptInterface(JAVASCRIPT_INTERFACE); - } - } - - protected void evaluateJavascriptWithFallback(String script) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - evaluateJavascript(script, null); - return; - } - - try { - loadUrl("javascript:" + URLEncoder.encode(script, "UTF-8")); - } catch (UnsupportedEncodingException e) { - // UTF-8 should always be supported - throw new RuntimeException(e); - } - } - - public void callInjectedJavaScript() { - if (getSettings().getJavaScriptEnabled() && - injectedJS != null && - !TextUtils.isEmpty(injectedJS)) { - evaluateJavascriptWithFallback("(function() {\n" + injectedJS + ";\n})();"); - } - } - - public void onMessage(String message) { - dispatchEvent(this, new TopMessageEvent(this.getId(), message)); - } - - protected void cleanupCallbacksAndDestroy() { - setWebViewClient(null); - destroy(); - } - } + private RNCWebViewPackage aPackage; public RNCWebViewManager() { mWebViewConfig = new WebViewConfig() { @@ -372,6 +118,13 @@ public class RNCWebViewManager extends SimpleViewManager { mWebViewConfig = webViewConfig; } + protected static void dispatchEvent(WebView webView, Event event) { + ReactContext reactContext = (ReactContext) webView.getContext(); + EventDispatcher eventDispatcher = + reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); + eventDispatcher.dispatchEvent(event); + } + @Override public String getName() { return REACT_CLASS; @@ -396,21 +149,21 @@ public class RNCWebViewManager extends SimpleViewManager { } - @Override - public void onProgressChanged(WebView webView, int newProgress) { + @Override + public void onProgressChanged(WebView webView, int newProgress) { super.onProgressChanged(webView, newProgress); WritableMap event = Arguments.createMap(); event.putDouble("target", webView.getId()); event.putString("title", webView.getTitle()); event.putBoolean("canGoBack", webView.canGoBack()); event.putBoolean("canGoForward", webView.canGoForward()); - event.putDouble("progress", (float)newProgress/100); + event.putDouble("progress", (float) newProgress / 100); dispatchEvent( - webView, - new TopLoadingProgressEvent( - webView.getId(), - event)); - } + webView, + new TopLoadingProgressEvent( + webView.getId(), + event)); + } @Override public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { @@ -420,9 +173,11 @@ public class RNCWebViewManager extends SimpleViewManager { protected void openFileChooser(ValueCallback filePathCallback, String acceptType) { getModule().startPhotoPickerIntent(filePathCallback, acceptType); } + protected void openFileChooser(ValueCallback filePathCallback) { getModule().startPhotoPickerIntent(filePathCallback, ""); } + protected void openFileChooser(ValueCallback filePathCallback, String acceptType, String capture) { getModule().startPhotoPickerIntent(filePathCallback, acceptType); } @@ -453,8 +208,8 @@ public class RNCWebViewManager extends SimpleViewManager { // Fixes broken full-screen modals/galleries due to body height being 0. webView.setLayoutParams( - new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); + new LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT)); setGeolocationEnabled(webView, false); if (ReactBuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { @@ -516,7 +271,7 @@ public class RNCWebViewManager extends SimpleViewManager { public void setShowsVerticalScrollIndicator(WebView view, boolean enabled) { view.setVerticalScrollBarEnabled(enabled); } - + @ReactProp(name = "cacheEnabled") public void setCacheEnabled(WebView view, boolean enabled) { if (enabled) { @@ -616,7 +371,7 @@ public class RNCWebViewManager extends SimpleViewManager { String html = source.getString("html"); if (source.hasKey("baseUrl")) { view.loadDataWithBaseURL( - source.getString("baseUrl"), html, HTML_MIME_TYPE, HTML_ENCODING, null); + source.getString("baseUrl"), html, HTML_MIME_TYPE, HTML_ENCODING, null); } else { view.loadData(html, HTML_MIME_TYPE + "; charset=" + HTML_ENCODING, null); } @@ -689,8 +444,8 @@ public class RNCWebViewManager extends SimpleViewManager { @ReactProp(name = "urlPrefixesForDefaultIntent") public void setUrlPrefixesForDefaultIntent( - WebView view, - @Nullable ReadableArray urlPrefixesForDefaultIntent) { + WebView view, + @Nullable ReadableArray urlPrefixesForDefaultIntent) { RNCWebViewClient client = ((RNCWebView) view).getRNCWebViewClient(); if (client != null && urlPrefixesForDefaultIntent != null) { client.setUrlPrefixesForDefaultIntent(urlPrefixesForDefaultIntent); @@ -729,16 +484,17 @@ public class RNCWebViewManager extends SimpleViewManager { } @Override - public @Nullable Map getCommandsMap() { + public @Nullable + Map getCommandsMap() { return MapBuilder.of( - "goBack", COMMAND_GO_BACK, - "goForward", COMMAND_GO_FORWARD, - "reload", COMMAND_RELOAD, - "stopLoading", COMMAND_STOP_LOADING, - "postMessage", COMMAND_POST_MESSAGE, - "injectJavaScript", COMMAND_INJECT_JAVASCRIPT, - "loadUrl", COMMAND_LOAD_URL - ); + "goBack", COMMAND_GO_BACK, + "goForward", COMMAND_GO_FORWARD, + "reload", COMMAND_RELOAD, + "stopLoading", COMMAND_STOP_LOADING, + "postMessage", COMMAND_POST_MESSAGE, + "injectJavaScript", COMMAND_INJECT_JAVASCRIPT, + "loadUrl", COMMAND_LOAD_URL + ); } @Override @@ -765,13 +521,13 @@ public class RNCWebViewManager extends SimpleViewManager { "var event;" + "var data = " + eventInitDict.toString() + ";" + "try {" + - "event = new MessageEvent('message', data);" + + "event = new MessageEvent('message', data);" + "} catch (e) {" + - "event = document.createEvent('MessageEvent');" + - "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" + + "event = document.createEvent('MessageEvent');" + + "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" + "}" + "document.dispatchEvent(event);" + - "})();"); + "})();"); } catch (JSONException e) { throw new RuntimeException(e); } @@ -796,13 +552,6 @@ public class RNCWebViewManager extends SimpleViewManager { ((RNCWebView) webView).cleanupCallbacksAndDestroy(); } - protected static void dispatchEvent(WebView webView, Event event) { - ReactContext reactContext = (ReactContext) webView.getContext(); - EventDispatcher eventDispatcher = - reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); - eventDispatcher.dispatchEvent(event); - } - public RNCWebViewPackage getPackage() { return this.aPackage; } @@ -814,4 +563,241 @@ public class RNCWebViewManager extends SimpleViewManager { public RNCWebViewModule getModule() { return this.aPackage.getModule(); } + + protected static class RNCWebViewClient extends WebViewClient { + + protected boolean mLastLoadFailed = false; + protected @Nullable + ReadableArray mUrlPrefixesForDefaultIntent; + + @Override + public void onPageFinished(WebView webView, String url) { + super.onPageFinished(webView, url); + + if (!mLastLoadFailed) { + RNCWebView reactWebView = (RNCWebView) webView; + + reactWebView.callInjectedJavaScript(); + + emitFinishEvent(webView, url); + } + } + + @Override + public void onPageStarted(WebView webView, String url, Bitmap favicon) { + super.onPageStarted(webView, url, favicon); + mLastLoadFailed = false; + + dispatchEvent( + webView, + new TopLoadingStartEvent( + webView.getId(), + createWebViewEvent(webView, url))); + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + dispatchEvent( + view, + new TopShouldStartLoadWithRequestEvent( + view.getId(), + createWebViewEvent(view, url))); + return true; + } + + + @TargetApi(Build.VERSION_CODES.N) + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + final String url = request.getUrl().toString(); + return this.shouldOverrideUrlLoading(view, url); + } + + @Override + public void onReceivedError( + WebView webView, + int errorCode, + String description, + String failingUrl) { + super.onReceivedError(webView, errorCode, description, failingUrl); + mLastLoadFailed = true; + + // In case of an error JS side expect to get a finish event first, and then get an error event + // Android WebView does it in the opposite way, so we need to simulate that behavior + emitFinishEvent(webView, failingUrl); + + WritableMap eventData = createWebViewEvent(webView, failingUrl); + eventData.putDouble("code", errorCode); + eventData.putString("description", description); + + dispatchEvent( + webView, + new TopLoadingErrorEvent(webView.getId(), eventData)); + } + + protected void emitFinishEvent(WebView webView, String url) { + dispatchEvent( + webView, + new TopLoadingFinishEvent( + webView.getId(), + createWebViewEvent(webView, url))); + } + + protected WritableMap createWebViewEvent(WebView webView, String url) { + WritableMap event = Arguments.createMap(); + event.putDouble("target", webView.getId()); + // Don't use webView.getUrl() here, the URL isn't updated to the new value yet in callbacks + // like onPageFinished + event.putString("url", url); + event.putBoolean("loading", !mLastLoadFailed && webView.getProgress() != 100); + event.putString("title", webView.getTitle()); + event.putBoolean("canGoBack", webView.canGoBack()); + event.putBoolean("canGoForward", webView.canGoForward()); + return event; + } + + public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) { + mUrlPrefixesForDefaultIntent = specialUrls; + } + } + + /** + * Subclass of {@link WebView} that implements {@link LifecycleEventListener} interface in order + * to call {@link WebView#destroy} on activity destroy event and also to clear the client + */ + protected static class RNCWebView extends WebView implements LifecycleEventListener { + protected @Nullable + String injectedJS; + protected boolean messagingEnabled = false; + protected @Nullable + RNCWebViewClient mRNCWebViewClient; + protected boolean sendContentSizeChangeEvents = false; + + /** + * WebView must be created with an context of the current activity + *

+ * Activity Context is required for creation of dialogs internally by WebView + * Reactive Native needed for access to ReactNative internal system functionality + */ + public RNCWebView(ThemedReactContext reactContext) { + super(reactContext); + } + + public void setSendContentSizeChangeEvents(boolean sendContentSizeChangeEvents) { + this.sendContentSizeChangeEvents = sendContentSizeChangeEvents; + } + + @Override + public void onHostResume() { + // do nothing + } + + @Override + public void onHostPause() { + // do nothing + } + + @Override + public void onHostDestroy() { + cleanupCallbacksAndDestroy(); + } + + @Override + protected void onSizeChanged(int w, int h, int ow, int oh) { + super.onSizeChanged(w, h, ow, oh); + + if (sendContentSizeChangeEvents) { + dispatchEvent( + this, + new ContentSizeChangeEvent( + this.getId(), + w, + h + ) + ); + } + } + + @Override + public void setWebViewClient(WebViewClient client) { + super.setWebViewClient(client); + mRNCWebViewClient = (RNCWebViewClient) client; + } + + public @Nullable + RNCWebViewClient getRNCWebViewClient() { + return mRNCWebViewClient; + } + + public void setInjectedJavaScript(@Nullable String js) { + injectedJS = js; + } + + protected RNCWebViewBridge createRNCWebViewBridge(RNCWebView webView) { + return new RNCWebViewBridge(webView); + } + + @SuppressLint("AddJavascriptInterface") + public void setMessagingEnabled(boolean enabled) { + if (messagingEnabled == enabled) { + return; + } + + messagingEnabled = enabled; + + if (enabled) { + addJavascriptInterface(createRNCWebViewBridge(this), JAVASCRIPT_INTERFACE); + } else { + removeJavascriptInterface(JAVASCRIPT_INTERFACE); + } + } + + protected void evaluateJavascriptWithFallback(String script) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + evaluateJavascript(script, null); + return; + } + + try { + loadUrl("javascript:" + URLEncoder.encode(script, "UTF-8")); + } catch (UnsupportedEncodingException e) { + // UTF-8 should always be supported + throw new RuntimeException(e); + } + } + + public void callInjectedJavaScript() { + if (getSettings().getJavaScriptEnabled() && + injectedJS != null && + !TextUtils.isEmpty(injectedJS)) { + evaluateJavascriptWithFallback("(function() {\n" + injectedJS + ";\n})();"); + } + } + + public void onMessage(String message) { + dispatchEvent(this, new TopMessageEvent(this.getId(), message)); + } + + protected void cleanupCallbacksAndDestroy() { + setWebViewClient(null); + destroy(); + } + + protected class RNCWebViewBridge { + RNCWebView mContext; + + RNCWebViewBridge(RNCWebView c) { + mContext = c; + } + + /** + * This method is called whenever JavaScript running within the web view calls: + * - window[JAVASCRIPT_INTERFACE].postMessage + */ + @JavascriptInterface + public void postMessage(String message) { + mContext.onMessage(message); + } + } + } } diff --git a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java index 8797064..1c0a34a 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java +++ b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java @@ -1,4 +1,3 @@ - package com.reactnativecommunity.webview; import android.Manifest; @@ -37,20 +36,35 @@ import static android.app.Activity.RESULT_OK; public class RNCWebViewModule extends ReactContextBaseJavaModule implements ActivityEventListener { - private final ReactApplicationContext reactContext; - private RNCWebViewPackage aPackage; - private static final int PICKER = 1; private static final int PICKER_LEGACY = 3; - + private static final int FILE_DOWNLOAD_PERMISSION_REQUEST = 1; + final String DEFAULT_MIME_TYPES = "*/*"; + private final ReactApplicationContext reactContext; + private RNCWebViewPackage aPackage; private ValueCallback filePathCallbackLegacy; private ValueCallback filePathCallback; private Uri outputFileUri; - private DownloadManager.Request downloadRequest; - private static final int FILE_DOWNLOAD_PERMISSION_REQUEST = 1; - - final String DEFAULT_MIME_TYPES = "*/*"; + private PermissionListener webviewFileDownloaderPermissionListener = new PermissionListener() { + @Override + public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + switch (requestCode) { + case FILE_DOWNLOAD_PERMISSION_REQUEST: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (downloadRequest != null) { + downloadFile(); + } + } else { + Toast.makeText(getCurrentActivity().getApplicationContext(), "Cannot download files as permission was denied. Please provide permission to write to storage, in order to download files.", Toast.LENGTH_LONG).show(); + } + return true; + } + } + return false; + } + }; public RNCWebViewModule(ReactApplicationContext reactContext) { super(reactContext); @@ -65,49 +79,49 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti @ReactMethod public void isFileUploadSupported(final Promise promise) { - Boolean result = false; - int current = Build.VERSION.SDK_INT; - if (current >= Build.VERSION_CODES.LOLLIPOP) { - result = true; - } - if (current >= Build.VERSION_CODES.JELLY_BEAN && current <= Build.VERSION_CODES.JELLY_BEAN_MR2) { - result = true; - } - promise.resolve(result); + Boolean result = false; + int current = Build.VERSION.SDK_INT; + if (current >= Build.VERSION_CODES.LOLLIPOP) { + result = true; + } + if (current >= Build.VERSION_CODES.JELLY_BEAN && current <= Build.VERSION_CODES.JELLY_BEAN_MR2) { + result = true; + } + promise.resolve(result); } public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { if (filePathCallback == null && filePathCallbackLegacy == null) { - return; + return; } // based off of which button was pressed, we get an activity result and a file // the camera activity doesn't properly return the filename* (I think?) so we use // this filename instead switch (requestCode) { - case PICKER: + case PICKER: if (resultCode != RESULT_OK) { - if (filePathCallback != null) { - filePathCallback.onReceiveValue(null); - } + if (filePathCallback != null) { + filePathCallback.onReceiveValue(null); + } } else { - Uri result[] = this.getSelectedFiles(data, resultCode); - if (result != null) { - filePathCallback.onReceiveValue(result); - } else { - filePathCallback.onReceiveValue(new Uri[] { outputFileUri }); - } + Uri result[] = this.getSelectedFiles(data, resultCode); + if (result != null) { + filePathCallback.onReceiveValue(result); + } else { + filePathCallback.onReceiveValue(new Uri[]{outputFileUri}); + } } break; - case PICKER_LEGACY: + case PICKER_LEGACY: Uri result = resultCode != Activity.RESULT_OK ? null : data == null ? outputFileUri : data.getData(); filePathCallbackLegacy.onReceiveValue(result); break; } filePathCallback = null; - filePathCallbackLegacy= null; + filePathCallbackLegacy = null; outputFileUri = null; } @@ -116,50 +130,50 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti private Uri[] getSelectedFiles(Intent data, int resultCode) { if (data == null) { - return null; + return null; } // we have one file selected if (data.getData() != null) { - if (resultCode == RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - return WebChromeClient.FileChooserParams.parseResult(resultCode, data); - } else { - return null; - } + if (resultCode == RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + return WebChromeClient.FileChooserParams.parseResult(resultCode, data); + } else { + return null; + } } // we have multiple files selected if (data.getClipData() != null) { - final int numSelectedFiles = data.getClipData().getItemCount(); - Uri[] result = new Uri[numSelectedFiles]; - for (int i = 0; i < numSelectedFiles; i++) { - result[i] = data.getClipData().getItemAt(i).getUri(); - } - return result; + final int numSelectedFiles = data.getClipData().getItemCount(); + Uri[] result = new Uri[numSelectedFiles]; + for (int i = 0; i < numSelectedFiles; i++) { + result[i] = data.getClipData().getItemAt(i).getUri(); + } + return result; } return null; } public void startPhotoPickerIntent(ValueCallback filePathCallback, String acceptType) { - filePathCallbackLegacy = filePathCallback; + filePathCallbackLegacy = filePathCallback; - Intent fileChooserIntent = getFileChooserIntent(acceptType); - Intent chooserIntent = Intent.createChooser(fileChooserIntent, ""); + Intent fileChooserIntent = getFileChooserIntent(acceptType); + Intent chooserIntent = Intent.createChooser(fileChooserIntent, ""); - ArrayList extraIntents = new ArrayList<>(); - if (acceptsImages(acceptType)) { - extraIntents.add(getPhotoIntent()); - } - if (acceptsVideo(acceptType)) { - extraIntents.add(getVideoIntent()); - } - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{})); + ArrayList extraIntents = new ArrayList<>(); + if (acceptsImages(acceptType)) { + extraIntents.add(getPhotoIntent()); + } + if (acceptsVideo(acceptType)) { + extraIntents.add(getVideoIntent()); + } + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{})); - if (chooserIntent.resolveActivity(getCurrentActivity().getPackageManager()) != null) { - getCurrentActivity().startActivityForResult(chooserIntent, PICKER_LEGACY); - } else { - Log.w("RNCWebViewModule", "there is no Activity to handle this Intent"); - } + if (chooserIntent.resolveActivity(getCurrentActivity().getPackageManager()) != null) { + getCurrentActivity().startActivityForResult(chooserIntent, PICKER_LEGACY); + } else { + Log.w("RNCWebViewModule", "there is no Activity to handle this Intent"); + } } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @@ -181,9 +195,9 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Parcelable[]{})); if (chooserIntent.resolveActivity(getCurrentActivity().getPackageManager()) != null) { - getCurrentActivity().startActivityForResult(chooserIntent, PICKER); + getCurrentActivity().startActivityForResult(chooserIntent, PICKER); } else { - Log.w("RNCWebViewModule", "there is no Activity to handle this Intent"); + Log.w("RNCWebViewModule", "there is no Activity to handle this Intent"); } return true; @@ -214,7 +228,7 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti if (!result) { PermissionAwareActivity activity = getPermissionAwareActivity(); - activity.requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE }, FILE_DOWNLOAD_PERMISSION_REQUEST, webviewFileDownloaderPermissionListener); + activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, FILE_DOWNLOAD_PERMISSION_REQUEST, webviewFileDownloaderPermissionListener); } return result; @@ -270,10 +284,11 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti private Boolean acceptsImages(String types) { String mimeType = types; if (types.matches("\\.\\w+")) { - mimeType = getMimeTypeFromExtension(types.replace(".", "")); + mimeType = getMimeTypeFromExtension(types.replace(".", "")); } return mimeType.isEmpty() || mimeType.toLowerCase().contains("image"); } + private Boolean acceptsImages(String[] types) { String[] mimeTypes = getAcceptedMimeType(types); return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "image"); @@ -282,38 +297,39 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti private Boolean acceptsVideo(String types) { String mimeType = types; if (types.matches("\\.\\w+")) { - mimeType = getMimeTypeFromExtension(types.replace(".", "")); + mimeType = getMimeTypeFromExtension(types.replace(".", "")); } return mimeType.isEmpty() || mimeType.toLowerCase().contains("video"); } + private Boolean acceptsVideo(String[] types) { String[] mimeTypes = getAcceptedMimeType(types); return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "video"); } - private Boolean arrayContainsString(String[] array, String pattern){ - for(String content : array){ - if(content.contains(pattern)){ - return true; - } + private Boolean arrayContainsString(String[] array, String pattern) { + for (String content : array) { + if (content.contains(pattern)) { + return true; + } } return false; } private String[] getAcceptedMimeType(String[] types) { if (isArrayEmpty(types)) { - return new String[]{DEFAULT_MIME_TYPES}; + return new String[]{DEFAULT_MIME_TYPES}; } String[] mimeTypes = new String[types.length]; for (int i = 0; i < types.length; i++) { - String t = types[i]; - // convert file extensions to mime types - if (t.matches("\\.\\w+")) { - String mimeType = getMimeTypeFromExtension(t.replace(".", "")); - mimeTypes[i] = mimeType; - } else { - mimeTypes[i] = t; - } + String t = types[i]; + // convert file extensions to mime types + if (t.matches("\\.\\w+")) { + String mimeType = getMimeTypeFromExtension(t.replace(".", "")); + mimeTypes[i] = mimeType; + } else { + mimeTypes[i] = t; + } } return mimeTypes; } @@ -321,7 +337,7 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti private String getMimeTypeFromExtension(String extension) { String type = null; if (extension != null) { - type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); } return type; } @@ -329,20 +345,20 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti private Uri getOutputUri(String intentType) { File capturedFile = null; try { - capturedFile = getCapturedFile(intentType); + capturedFile = getCapturedFile(intentType); } catch (IOException e) { - Log.e("CREATE FILE", "Error occurred while creating the File", e); - e.printStackTrace(); + Log.e("CREATE FILE", "Error occurred while creating the File", e); + e.printStackTrace(); } // for versions below 6.0 (23) we use the old File creation & permissions model if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return Uri.fromFile(capturedFile); + return Uri.fromFile(capturedFile); } // for versions 6.0+ (23) we use the FileProvider to avoid runtime permissions String packageName = getReactApplicationContext().getPackageName(); - return FileProvider.getUriForFile(getReactApplicationContext(), packageName+".fileprovider", capturedFile); + return FileProvider.getUriForFile(getReactApplicationContext(), packageName + ".fileprovider", capturedFile); } private File getCapturedFile(String intentType) throws IOException { @@ -365,10 +381,10 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti // for versions below 6.0 (23) we use the old File creation & permissions model if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - // only this Directory works on all tested Android versions - // ctx.getExternalFilesDir(dir) was failing on Android 5.0 (sdk 21) - File storageDir = Environment.getExternalStoragePublicDirectory(dir); - return new File(storageDir, filename); + // only this Directory works on all tested Android versions + // ctx.getExternalFilesDir(dir) was failing on Android 5.0 (sdk 21) + File storageDir = Environment.getExternalStoragePublicDirectory(dir); + return new File(storageDir, filename); } File storageDir = getReactApplicationContext().getExternalFilesDir(null); @@ -385,30 +401,10 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti private PermissionAwareActivity getPermissionAwareActivity() { Activity activity = getCurrentActivity(); if (activity == null) { - throw new IllegalStateException("Tried to use permissions API while not attached to an Activity."); + throw new IllegalStateException("Tried to use permissions API while not attached to an Activity."); } else if (!(activity instanceof PermissionAwareActivity)) { - throw new IllegalStateException("Tried to use permissions API but the host Activity doesn't implement PermissionAwareActivity."); + throw new IllegalStateException("Tried to use permissions API but the host Activity doesn't implement PermissionAwareActivity."); } return (PermissionAwareActivity) activity; } - - private PermissionListener webviewFileDownloaderPermissionListener = new PermissionListener() { - @Override - public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - switch (requestCode) { - case FILE_DOWNLOAD_PERMISSION_REQUEST: { - // If request is cancelled, the result arrays are empty. - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (downloadRequest != null) { - downloadFile(); - } - } else { - Toast.makeText(getCurrentActivity().getApplicationContext(), "Cannot download files as permission was denied. Please provide permission to write to storage, in order to download files.", Toast.LENGTH_LONG).show(); - } - return true; - } - } - return false; - } - }; } diff --git a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java index f8817c0..2476bdb 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java +++ b/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java @@ -1,44 +1,43 @@ - package com.reactnativecommunity.webview; +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.bridge.JavaScriptModule; - public class RNCWebViewPackage implements ReactPackage { - private RNCWebViewManager manager; - private RNCWebViewModule module; + private RNCWebViewManager manager; + private RNCWebViewModule module; - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - List modulesList = new ArrayList<>(); - module = new RNCWebViewModule(reactContext); - module.setPackage(this); - modulesList.add(module); - return modulesList; - } + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modulesList = new ArrayList<>(); + module = new RNCWebViewModule(reactContext); + module.setPackage(this); + modulesList.add(module); + return modulesList; + } - // Deprecated from RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); - } + // Deprecated from RN 0.47 + public List> createJSModules() { + return Collections.emptyList(); + } - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - manager = new RNCWebViewManager(); - manager.setPackage(this); - return Arrays.asList(manager); - } + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + manager = new RNCWebViewManager(); + manager.setPackage(this); + return Arrays.asList(manager); + } - public RNCWebViewModule getModule() { - return module; - } + public RNCWebViewModule getModule() { + return module; + } } diff --git a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingErrorEvent.kt b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingErrorEvent.kt index 554e249..7f5096d 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingErrorEvent.kt +++ b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingErrorEvent.kt @@ -8,18 +8,18 @@ import com.facebook.react.uimanager.events.RCTEventEmitter * Event emitted when there is an error in loading. */ class TopLoadingErrorEvent(viewId: Int, private val mEventData: WritableMap) : - Event(viewId) { - companion object { - const val EVENT_NAME = "topLoadingError" - } + Event(viewId) { + companion object { + const val EVENT_NAME = "topLoadingError" + } - override fun getEventName(): String = EVENT_NAME + override fun getEventName(): String = EVENT_NAME - override fun canCoalesce(): Boolean = false + override fun canCoalesce(): Boolean = false - override fun getCoalescingKey(): Short = 0 + override fun getCoalescingKey(): Short = 0 - override fun dispatch(rctEventEmitter: RCTEventEmitter) = - rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) + override fun dispatch(rctEventEmitter: RCTEventEmitter) = + rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) } diff --git a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingFinishEvent.kt b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingFinishEvent.kt index 90bb5c5..20da841 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingFinishEvent.kt +++ b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingFinishEvent.kt @@ -8,17 +8,17 @@ import com.facebook.react.uimanager.events.RCTEventEmitter * Event emitted when loading is completed. */ class TopLoadingFinishEvent(viewId: Int, private val mEventData: WritableMap) : - Event(viewId) { - companion object { - const val EVENT_NAME = "topLoadingFinish" - } + Event(viewId) { + companion object { + const val EVENT_NAME = "topLoadingFinish" + } - override fun getEventName(): String = EVENT_NAME + override fun getEventName(): String = EVENT_NAME - override fun canCoalesce(): Boolean = false + override fun canCoalesce(): Boolean = false - override fun getCoalescingKey(): Short = 0 + override fun getCoalescingKey(): Short = 0 - override fun dispatch(rctEventEmitter: RCTEventEmitter) = - rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) + override fun dispatch(rctEventEmitter: RCTEventEmitter) = + rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) } diff --git a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingProgressEvent.kt b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingProgressEvent.kt index 9916cc3..0d46970 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingProgressEvent.kt +++ b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingProgressEvent.kt @@ -8,17 +8,17 @@ import com.facebook.react.uimanager.events.RCTEventEmitter * Event emitted when there is a loading progress event. */ class TopLoadingProgressEvent(viewId: Int, private val mEventData: WritableMap) : - Event(viewId) { - companion object { - const val EVENT_NAME = "topLoadingProgress" - } + Event(viewId) { + companion object { + const val EVENT_NAME = "topLoadingProgress" + } - override fun getEventName(): String = EVENT_NAME + override fun getEventName(): String = EVENT_NAME - override fun canCoalesce(): Boolean = false + override fun canCoalesce(): Boolean = false - override fun getCoalescingKey(): Short = 0 + override fun getCoalescingKey(): Short = 0 - override fun dispatch(rctEventEmitter: RCTEventEmitter) = - rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) + override fun dispatch(rctEventEmitter: RCTEventEmitter) = + rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) } diff --git a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingStartEvent.kt b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingStartEvent.kt index fdc2159..cac21a2 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingStartEvent.kt +++ b/android/src/main/java/com/reactnativecommunity/webview/events/TopLoadingStartEvent.kt @@ -8,18 +8,18 @@ import com.facebook.react.uimanager.events.RCTEventEmitter * Event emitted when loading has started */ class TopLoadingStartEvent(viewId: Int, private val mEventData: WritableMap) : - Event(viewId) { - companion object { - const val EVENT_NAME = "topLoadingStart" - } + Event(viewId) { + companion object { + const val EVENT_NAME = "topLoadingStart" + } - override fun getEventName(): String = EVENT_NAME + override fun getEventName(): String = EVENT_NAME - override fun canCoalesce(): Boolean = false + override fun canCoalesce(): Boolean = false - override fun getCoalescingKey(): Short = 0 + override fun getCoalescingKey(): Short = 0 - override fun dispatch(rctEventEmitter: RCTEventEmitter) = - rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) + override fun dispatch(rctEventEmitter: RCTEventEmitter) = + rctEventEmitter.receiveEvent(viewTag, eventName, mEventData) } diff --git a/android/src/main/java/com/reactnativecommunity/webview/events/TopMessageEvent.kt b/android/src/main/java/com/reactnativecommunity/webview/events/TopMessageEvent.kt index b9d9152..c9fa8f9 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/events/TopMessageEvent.kt +++ b/android/src/main/java/com/reactnativecommunity/webview/events/TopMessageEvent.kt @@ -8,19 +8,19 @@ import com.facebook.react.uimanager.events.RCTEventEmitter * Event emitted when there is an error in loading. */ class TopMessageEvent(viewId: Int, private val mData: String) : Event(viewId) { - companion object { - const val EVENT_NAME = "topMessage" - } + companion object { + const val EVENT_NAME = "topMessage" + } - override fun getEventName(): String = EVENT_NAME + override fun getEventName(): String = EVENT_NAME - override fun canCoalesce(): Boolean = false + override fun canCoalesce(): Boolean = false - override fun getCoalescingKey(): Short = 0 + override fun getCoalescingKey(): Short = 0 - override fun dispatch(rctEventEmitter: RCTEventEmitter) { - val data = Arguments.createMap() - data.putString("data", mData) - rctEventEmitter.receiveEvent(viewTag, EVENT_NAME, data) - } + override fun dispatch(rctEventEmitter: RCTEventEmitter) { + val data = Arguments.createMap() + data.putString("data", mData) + rctEventEmitter.receiveEvent(viewTag, EVENT_NAME, data) + } } diff --git a/android/src/main/java/com/reactnativecommunity/webview/events/TopShouldStartLoadWithRequestEvent.kt b/android/src/main/java/com/reactnativecommunity/webview/events/TopShouldStartLoadWithRequestEvent.kt index c576773..0f80ced 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/events/TopShouldStartLoadWithRequestEvent.kt +++ b/android/src/main/java/com/reactnativecommunity/webview/events/TopShouldStartLoadWithRequestEvent.kt @@ -8,20 +8,20 @@ import com.facebook.react.uimanager.events.RCTEventEmitter * Event emitted when shouldOverrideUrlLoading is called */ class TopShouldStartLoadWithRequestEvent(viewId: Int, private val mData: WritableMap) : Event(viewId) { - companion object { - const val EVENT_NAME = "topShouldStartLoadWithRequest" - } + companion object { + const val EVENT_NAME = "topShouldStartLoadWithRequest" + } - init { - mData.putString("navigationType", "other") - } + init { + mData.putString("navigationType", "other") + } - override fun getEventName(): String = EVENT_NAME + override fun getEventName(): String = EVENT_NAME - override fun canCoalesce(): Boolean = false + override fun canCoalesce(): Boolean = false - override fun getCoalescingKey(): Short = 0 + override fun getCoalescingKey(): Short = 0 - override fun dispatch(rctEventEmitter: RCTEventEmitter) = - rctEventEmitter.receiveEvent(viewTag, EVENT_NAME, mData) + override fun dispatch(rctEventEmitter: RCTEventEmitter) = + rctEventEmitter.receiveEvent(viewTag, EVENT_NAME, mData) } diff --git a/android/src/main/res/xml/file_provider_paths.xml b/android/src/main/res/xml/file_provider_paths.xml index d04c4ca..aba5f56 100644 --- a/android/src/main/res/xml/file_provider_paths.xml +++ b/android/src/main/res/xml/file_provider_paths.xml @@ -1,4 +1,6 @@ - - + +