Updated Android context menu workaround, updated iOS onCreateContextMenu event, Added Android keyboard workaround to hide the keyboard when clicking other HTML elements
This commit is contained in:
parent
5943059b1d
commit
f569e369f4
|
@ -1,3 +1,9 @@
|
||||||
|
## 3.3.0
|
||||||
|
|
||||||
|
- Updated Android context menu workaround
|
||||||
|
- Calling `onCreateContextMenu` event on iOS also when the context menu is disabled in order to have the same effect as Android
|
||||||
|
- Added Android keyboard workaround to hide the keyboard when clicking other HTML elements, losing the focus on the previous input
|
||||||
|
|
||||||
## 3.2.0
|
## 3.2.0
|
||||||
|
|
||||||
- Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235)
|
- Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235)
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextThemeWrapper;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.webkit.WebChromeClient;
|
import android.webkit.WebChromeClient;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.DisplayListenerProxy;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewOptions;
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||||
|
|
||||||
|
@ -29,7 +24,6 @@ import java.util.Map;
|
||||||
import io.flutter.plugin.common.BinaryMessenger;
|
import io.flutter.plugin.common.BinaryMessenger;
|
||||||
import io.flutter.plugin.common.MethodCall;
|
import io.flutter.plugin.common.MethodCall;
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
import io.flutter.plugin.common.PluginRegistry.Registrar;
|
|
||||||
import io.flutter.plugin.platform.PlatformView;
|
import io.flutter.plugin.platform.PlatformView;
|
||||||
|
|
||||||
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
||||||
|
|
|
@ -76,18 +76,17 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
|
int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
|
||||||
public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler();
|
public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler();
|
||||||
public Pattern regexToCancelSubFramesLoadingCompiled;
|
public Pattern regexToCancelSubFramesLoadingCompiled;
|
||||||
private GestureDetector gestureDetector = null;
|
public GestureDetector gestureDetector = null;
|
||||||
private MotionEvent motionEvent = null;
|
public LinearLayout floatingContextMenu = null;
|
||||||
private LinearLayout floatingContextMenu = null;
|
|
||||||
public HashMap<String, Object> contextMenu = null;
|
public HashMap<String, Object> contextMenu = null;
|
||||||
public Handler headlessHandler = new Handler(Looper.getMainLooper());
|
public Handler headlessHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
private Runnable checkScrollStoppedTask;
|
public Runnable checkScrollStoppedTask;
|
||||||
private int initialPositionScrollStoppedTask;
|
public int initialPositionScrollStoppedTask;
|
||||||
private int newCheckScrollStoppedTask = 100;
|
public int newCheckScrollStoppedTask = 100; // ms
|
||||||
|
|
||||||
private Runnable selectedTextTask;
|
public Runnable checkContextMenuShouldBeClosedTask;
|
||||||
private int newCheckSelectedTextTask = 100;
|
public int newCheckContextMenuShouldBeClosedTaskTask = 100; // ms
|
||||||
|
|
||||||
static final String consoleLogJS = "(function(console) {" +
|
static final String consoleLogJS = "(function(console) {" +
|
||||||
" var oldLogs = {" +
|
" var oldLogs = {" +
|
||||||
|
@ -117,7 +116,7 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
|
|
||||||
static final String printJS = "window.print = function() {" +
|
static final String printJS = "window.print = function() {" +
|
||||||
" window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" +
|
" window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" +
|
||||||
"}";
|
"};";
|
||||||
|
|
||||||
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));";
|
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));";
|
||||||
|
|
||||||
|
@ -531,6 +530,14 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
" };" +
|
" };" +
|
||||||
"})(window.fetch);";
|
"})(window.fetch);";
|
||||||
|
|
||||||
|
static final String isActiveElementInputEditableJS =
|
||||||
|
"var activeEl = document.activeElement;" +
|
||||||
|
"var nodeName = (activeEl != null) ? activeEl.nodeName.toLowerCase() : '';" +
|
||||||
|
"var isActiveElementInputEditable = activeEl != null && " +
|
||||||
|
"(activeEl.nodeType == 1 && (nodeName == 'textarea' || (nodeName == 'input' && /^(?:text|email|number|search|tel|url|password)$/i.test(activeEl.type != null ? activeEl.type : 'text')))) && " +
|
||||||
|
"!activeEl.disabled && !activeEl.readOnly;" +
|
||||||
|
"var isActiveElementEditable = isActiveElementInputEditable || (activeEl != null && activeEl.isContentEditable) || document.designMode === 'on';";
|
||||||
|
|
||||||
static final String getSelectedTextJS = "(function(){" +
|
static final String getSelectedTextJS = "(function(){" +
|
||||||
" var txt;" +
|
" var txt;" +
|
||||||
" if (window.getSelection) {" +
|
" if (window.getSelection) {" +
|
||||||
|
@ -543,6 +550,48 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
" return txt;" +
|
" return txt;" +
|
||||||
"})();";
|
"})();";
|
||||||
|
|
||||||
|
// android Workaround to hide context menu when selected text is empty
|
||||||
|
// and the document active element is not an input element.
|
||||||
|
static final String checkContextMenuShouldBeHiddenJS = "(function(){" +
|
||||||
|
" var txt;" +
|
||||||
|
" if (window.getSelection) {" +
|
||||||
|
" txt = window.getSelection().toString();" +
|
||||||
|
" } else if (window.document.getSelection) {" +
|
||||||
|
" txt = window.document.getSelection().toString();" +
|
||||||
|
" } else if (window.document.selection) {" +
|
||||||
|
" txt = window.document.selection.createRange().text;" +
|
||||||
|
" }" +
|
||||||
|
isActiveElementInputEditableJS +
|
||||||
|
" return txt === '' && !isActiveElementEditable;" +
|
||||||
|
"})();";
|
||||||
|
|
||||||
|
// android Workaround to hide context menu when user emit a keydown event
|
||||||
|
static final String checkGlobalKeyDownEventToHideContextMenuJS = "(function(){" +
|
||||||
|
" document.addEventListener('keydown', function(e) {" +
|
||||||
|
" window." + JavaScriptBridgeInterface.name + "._hideContextMenu();" +
|
||||||
|
" });" +
|
||||||
|
"})();";
|
||||||
|
|
||||||
|
// android Workaround to hide the Keyboard when the user click outside
|
||||||
|
// on something not focusable such as input or a textarea.
|
||||||
|
static final String androidKeyboardWorkaroundFocusoutEventJS = "(function(){" +
|
||||||
|
" var isFocusin = false;" +
|
||||||
|
" document.addEventListener('focusin', function(e) {" +
|
||||||
|
" var nodeName = e.target.nodeName.toLowerCase();" +
|
||||||
|
" var isInputButton = nodeName === 'input' && e.target.type != null && e.target.type === 'button';" +
|
||||||
|
" isFocusin = (['a', 'area', 'button', 'details', 'iframe', 'select', 'summary'].indexOf(nodeName) >= 0 || isInputButton) ? false : true;" +
|
||||||
|
" });" +
|
||||||
|
" document.addEventListener('focusout', function(e) {" +
|
||||||
|
" isFocusin = false;" +
|
||||||
|
" setTimeout(function() {" +
|
||||||
|
isActiveElementInputEditableJS +
|
||||||
|
" if (!isFocusin && !isActiveElementEditable) {" +
|
||||||
|
" window." + JavaScriptBridgeInterface.name + ".callHandler('androidKeyboardWorkaroundFocusoutEvent');" +
|
||||||
|
" }" +
|
||||||
|
" }, 300);" +
|
||||||
|
" });" +
|
||||||
|
"})();";
|
||||||
|
|
||||||
public InAppWebView(Context context) {
|
public InAppWebView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
@ -746,19 +795,19 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
selectedTextTask = new Runnable() {
|
checkContextMenuShouldBeClosedTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (floatingContextMenu != null) {
|
if (floatingContextMenu != null) {
|
||||||
getSelectedText(new ValueCallback<String>() {
|
evaluateJavascript(checkContextMenuShouldBeHiddenJS, new ValueCallback<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceiveValue(String value) {
|
public void onReceiveValue(String value) {
|
||||||
if (value == null || value.length() == 0) {
|
if (value == null || value.equals("true")) {
|
||||||
if (floatingContextMenu != null) {
|
if (floatingContextMenu != null) {
|
||||||
hideContextMenu();
|
hideContextMenu();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
headlessHandler.postDelayed(selectedTextTask, newCheckSelectedTextTask);
|
headlessHandler.postDelayed(checkContextMenuShouldBeClosedTask, newCheckContextMenuShouldBeClosedTaskTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1424,14 +1473,18 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
PrintManager printManager = (PrintManager) Shared.activity.getApplicationContext()
|
PrintManager printManager = (PrintManager) Shared.activity.getApplicationContext()
|
||||||
.getSystemService(Context.PRINT_SERVICE);
|
.getSystemService(Context.PRINT_SERVICE);
|
||||||
|
|
||||||
String jobName = getTitle() + " Document";
|
if (printManager != null) {
|
||||||
|
String jobName = getTitle() + " Document";
|
||||||
|
|
||||||
// Get a printCurrentPage adapter instance
|
// Get a printCurrentPage adapter instance
|
||||||
PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName);
|
PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName);
|
||||||
|
|
||||||
// Create a printCurrentPage job with name and adapter instance
|
// Create a printCurrentPage job with name and adapter instance
|
||||||
printManager.print(jobName, printAdapter,
|
printManager.print(jobName, printAdapter,
|
||||||
new PrintAttributes.Builder().build());
|
new PrintAttributes.Builder().build());
|
||||||
|
} else {
|
||||||
|
Log.e(LOG_TAG, "No PrintManager available");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Float getUpdatedScale() {
|
public Float getUpdatedScale() {
|
||||||
|
@ -1444,6 +1497,12 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
sendOnCreateContextMenuEvent();
|
sendOnCreateContextMenuEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCheckIsTextEditor() {
|
||||||
|
Log.d(LOG_TAG, "onCheckIsTextEditor");
|
||||||
|
return super.onCheckIsTextEditor();
|
||||||
|
}
|
||||||
|
|
||||||
private void sendOnCreateContextMenuEvent() {
|
private void sendOnCreateContextMenuEvent() {
|
||||||
HitTestResult hitTestResult = getHitTestResult();
|
HitTestResult hitTestResult = getHitTestResult();
|
||||||
Map<String, Object> hitTestResultMap = new HashMap<>();
|
Map<String, Object> hitTestResultMap = new HashMap<>();
|
||||||
|
@ -1545,7 +1604,7 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
text.setOnClickListener(new OnClickListener() {
|
text.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
clearFocus();
|
// clearFocus();
|
||||||
hideContextMenu();
|
hideContextMenu();
|
||||||
|
|
||||||
Map<String, Object> obj = new HashMap<>();
|
Map<String, Object> obj = new HashMap<>();
|
||||||
|
@ -1588,8 +1647,8 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
if (hasBeenRemovedAndRebuilt) {
|
if (hasBeenRemovedAndRebuilt) {
|
||||||
sendOnCreateContextMenuEvent();
|
sendOnCreateContextMenuEvent();
|
||||||
}
|
}
|
||||||
if (selectedTextTask != null) {
|
if (checkContextMenuShouldBeClosedTask != null) {
|
||||||
selectedTextTask.run();
|
checkContextMenuShouldBeClosedTask.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actionMenu.clear();
|
actionMenu.clear();
|
||||||
|
|
|
@ -179,6 +179,10 @@ public class InAppWebViewClient extends WebViewClient {
|
||||||
if (webView.options.useOnLoadResource) {
|
if (webView.options.useOnLoadResource) {
|
||||||
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
|
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
|
||||||
}
|
}
|
||||||
|
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", "");
|
||||||
|
if (flutterWebView != null) {
|
||||||
|
js += InAppWebView.androidKeyboardWorkaroundFocusoutEventJS.replaceAll("[\r\n]+", "");
|
||||||
|
}
|
||||||
js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
|
js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
|
|
@ -44,6 +44,21 @@ public class JavaScriptBridgeInterface {
|
||||||
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
|
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
public void _hideContextMenu() {
|
||||||
|
final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView;
|
||||||
|
|
||||||
|
final Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (webView != null && webView.floatingContextMenu != null) {
|
||||||
|
webView.hideContextMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void _callHandler(final String handlerName, final String _callHandlerID, final String args) {
|
public void _callHandler(final String handlerName, final String _callHandlerID, final String args) {
|
||||||
final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView;
|
final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"android":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_macos-0.1.0+3/","dependencies":[]},{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos"]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-21 03:31:36.578209","version":"1.17.0"}
|
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_inappwebview-3.2.0/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"android":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_inappwebview-3.2.0/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_macos-0.1.0+3/","dependencies":[]},{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos"]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-21 22:50:56.107907","version":"1.17.0"}
|
|
@ -2,7 +2,7 @@
|
||||||
# This is a generated file; do not edit or check into version control.
|
# This is a generated file; do not edit or check into version control.
|
||||||
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
|
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
|
||||||
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
|
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
|
||||||
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/test_driver/app.dart"
|
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
|
||||||
export "FLUTTER_BUILD_DIR=build"
|
export "FLUTTER_BUILD_DIR=build"
|
||||||
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
||||||
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
|
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
|
|
||||||
import 'main.dart';
|
import 'main.dart';
|
||||||
|
@ -78,7 +81,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
||||||
initialHeaders: {},
|
initialHeaders: {},
|
||||||
initialOptions: InAppWebViewGroupOptions(
|
initialOptions: InAppWebViewGroupOptions(
|
||||||
crossPlatform: InAppWebViewOptions(
|
crossPlatform: InAppWebViewOptions(
|
||||||
debuggingEnabled: true
|
debuggingEnabled: true,
|
||||||
|
disableContextMenu: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onWebViewCreated: (InAppWebViewController controller) {
|
onWebViewCreated: (InAppWebViewController controller) {
|
||||||
|
|
|
@ -24,8 +24,8 @@ dependencies:
|
||||||
path_provider: ^1.4.0
|
path_provider: ^1.4.0
|
||||||
permission_handler: ^3.3.0
|
permission_handler: ^3.3.0
|
||||||
connectivity: ^0.4.5+6
|
connectivity: ^0.4.5+6
|
||||||
flutter_inappwebview:
|
flutter_inappwebview: ^3.2.0
|
||||||
path: ../
|
#path: ../
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_driver:
|
flutter_driver:
|
||||||
|
|
|
@ -763,6 +763,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
||||||
var lastTouchPointTimestamp = Int64(Date().timeIntervalSince1970 * 1000)
|
var lastTouchPointTimestamp = Int64(Date().timeIntervalSince1970 * 1000)
|
||||||
|
|
||||||
var contextMenuIsShowing = false
|
var contextMenuIsShowing = false
|
||||||
|
// flag used for the workaround to trigger onCreateContextMenu event as the same on Android
|
||||||
|
var onCreateContextMenuEventTriggeredWhenMenuDisabled = false
|
||||||
|
|
||||||
var customIMPs: [IMP] = []
|
var customIMPs: [IMP] = []
|
||||||
|
|
||||||
|
@ -887,10 +889,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
||||||
|
|
||||||
return super.hitTest(point, with: event)
|
return super.hitTest(point, with: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
||||||
if let _ = sender as? UIMenuController {
|
if let _ = sender as? UIMenuController {
|
||||||
if self.options?.disableContextMenu == true {
|
if self.options?.disableContextMenu == true {
|
||||||
|
if !onCreateContextMenuEventTriggeredWhenMenuDisabled {
|
||||||
|
// workaround to trigger onCreateContextMenu event as the same on Android
|
||||||
|
self.onCreateContextMenu()
|
||||||
|
onCreateContextMenuEventTriggeredWhenMenuDisabled = true
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
|
self.onCreateContextMenuEventTriggeredWhenMenuDisabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") {
|
if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") {
|
||||||
|
@ -1083,8 +1093,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
||||||
if (options?.clearCache)! {
|
if (options?.clearCache)! {
|
||||||
clearCache()
|
clearCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 10.0, *)
|
@available(iOS 10.0, *)
|
||||||
|
|
|
@ -18,7 +18,8 @@ const javaScriptHandlerForbiddenNames = [
|
||||||
"onAjaxReadyStateChange",
|
"onAjaxReadyStateChange",
|
||||||
"onAjaxProgress",
|
"onAjaxProgress",
|
||||||
"shouldInterceptFetchRequest",
|
"shouldInterceptFetchRequest",
|
||||||
"onPrint"
|
"onPrint",
|
||||||
|
"androidKeyboardWorkaroundFocusoutEvent"
|
||||||
];
|
];
|
||||||
|
|
||||||
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
|
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
|
||||||
|
|
|
@ -439,6 +439,11 @@ class InAppWebViewController {
|
||||||
List<dynamic> args = jsonDecode(call.arguments["args"]);
|
List<dynamic> args = jsonDecode(call.arguments["args"]);
|
||||||
|
|
||||||
switch (handlerName) {
|
switch (handlerName) {
|
||||||
|
case "androidKeyboardWorkaroundFocusoutEvent":
|
||||||
|
// android Workaround to hide the Keyboard when the user click outside
|
||||||
|
// on something not focusable such as input or a textarea.
|
||||||
|
SystemChannels.textInput.invokeMethod("TextInput.hide");
|
||||||
|
break;
|
||||||
case "onLoadResource":
|
case "onLoadResource":
|
||||||
Map<dynamic, dynamic> argMap = args[0];
|
Map<dynamic, dynamic> argMap = args[0];
|
||||||
String initiatorType = argMap["initiatorType"];
|
String initiatorType = argMap["initiatorType"];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_inappwebview
|
name: flutter_inappwebview
|
||||||
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
|
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
|
||||||
version: 3.2.0
|
version: 3.3.0
|
||||||
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
Loading…
Reference in New Issue