Commit 5943059b authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

v3.2.0, added context menu classes, updated docs, fix #235, fix #337, fix #341

parent ecf8d45d
## 3.1.1 ## 3.2.0
- Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235)
- Added `onCreateContextMenu`, `onHideContextMenu`, `onContextMenuActionItemClicked` context menu events
- Added `contextMenu` to WebView
- Added `disableContextMenu` WebView option
- Added `getSelectedText`, `getHitTestResult` methods to WebView Controller
- Fixed `Confirmation dialog (onbeforeunload) displayed after popped from webview page` [#337](https://github.com/pichillilorenzo/flutter_inappwebview/issues/337) - Fixed `Confirmation dialog (onbeforeunload) displayed after popped from webview page` [#337](https://github.com/pichillilorenzo/flutter_inappwebview/issues/337)
- Fixed `CookieManager.setCookie` `expiresDate` option - Fixed `CookieManager.setCookie` `expiresDate` option
- Fixed `Scrolling not smooth on iOS` [#341](https://github.com/pichillilorenzo/flutter_inappwebview/issues/341)
### BREAKING CHANGES
- Renamed `LongPressHitTestResult` to `InAppWebViewHitTestResult`.
- Renamed `LongPressHitTestResultType` to `InAppWebViewHitTestResultType`.
## 3.1.0 ## 3.1.0
......
This diff is collapsed.
...@@ -136,6 +136,7 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel. ...@@ -136,6 +136,7 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
myIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); myIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Shared.activity.startActivity(myIntent); Shared.activity.startActivity(myIntent);
result.success(true);
break; break;
default: default:
result.notImplemented(); result.notImplemented();
......
...@@ -40,11 +40,12 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl ...@@ -40,11 +40,12 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
{ {
String url = (String) call.argument("url"); String url = (String) call.argument("url");
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options"); HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList");
String uuidFallback = (String) call.argument("uuidFallback"); String uuidFallback = (String) call.argument("uuidFallback");
Map<String, String> headersFallback = (Map<String, String>) call.argument("headersFallback"); Map<String, String> headersFallback = (Map<String, String>) call.argument("headersFallback");
HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback"); HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList"); HashMap<String, Object> contextMenuFallback = (HashMap<String, Object>) call.argument("contextMenuFallback");
open(activity, uuid, url, options, uuidFallback, headersFallback, optionsFallback, menuItemList, result); open(activity, uuid, url, options, menuItemList, uuidFallback, headersFallback, optionsFallback, contextMenuFallback, result);
} }
break; break;
default: default:
...@@ -52,8 +53,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl ...@@ -52,8 +53,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
} }
} }
public void open(Activity activity, String uuid, String url, HashMap<String, Object> options, String uuidFallback, public void open(Activity activity, String uuid, String url, HashMap<String, Object> options, List<HashMap<String, Object>> menuItemList, String uuidFallback,
Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, List<HashMap<String, Object>> menuItemList, MethodChannel.Result result) { Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, HashMap<String, Object> contextMenuFallback, MethodChannel.Result result) {
Intent intent = null; Intent intent = null;
Bundle extras = new Bundle(); Bundle extras = new Bundle();
...@@ -62,9 +63,11 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl ...@@ -62,9 +63,11 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
extras.putBoolean("isData", false); extras.putBoolean("isData", false);
extras.putString("uuid", uuid); extras.putString("uuid", uuid);
extras.putSerializable("options", options); extras.putSerializable("options", options);
extras.putSerializable("headers", (Serializable) headersFallback);
extras.putSerializable("menuItemList", (Serializable) menuItemList); extras.putSerializable("menuItemList", (Serializable) menuItemList);
extras.putSerializable("headers", (Serializable) headersFallback);
extras.putSerializable("contextMenu", (Serializable) contextMenuFallback);
if (CustomTabActivityHelper.isAvailable(activity)) { if (CustomTabActivityHelper.isAvailable(activity)) {
intent = new Intent(activity, ChromeCustomTabsActivity.class); intent = new Intent(activity, ChromeCustomTabsActivity.class);
} }
......
...@@ -72,6 +72,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -72,6 +72,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
fromActivity = b.getString("fromActivity"); fromActivity = b.getString("fromActivity");
HashMap<String, Object> optionsMap = (HashMap<String, Object>) b.getSerializable("options"); HashMap<String, Object> optionsMap = (HashMap<String, Object>) b.getSerializable("options");
HashMap<String, Object> contextMenu = (HashMap<String, Object>) b.getSerializable("contextMenu");
options = new InAppBrowserOptions(); options = new InAppBrowserOptions();
options.parse(optionsMap); options.parse(optionsMap);
...@@ -79,6 +80,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -79,6 +80,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
InAppWebViewOptions webViewOptions = new InAppWebViewOptions(); InAppWebViewOptions webViewOptions = new InAppWebViewOptions();
webViewOptions.parse(optionsMap); webViewOptions.parse(optionsMap);
webView.options = webViewOptions; webView.options = webViewOptions;
webView.contextMenu = contextMenu;
actionBar = getSupportActionBar(); actionBar = getSupportActionBar();
...@@ -223,7 +225,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -223,7 +225,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
result.success(isHidden); result.success(isHidden);
break; break;
case "takeScreenshot": case "takeScreenshot":
result.success(takeScreenshot()); takeScreenshot(result);
break; break;
case "setOptions": case "setOptions":
{ {
...@@ -330,6 +332,16 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -330,6 +332,16 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
case "getScale": case "getScale":
result.success(getScale()); result.success(getScale());
break; break;
case "getSelectedText":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getSelectedText(result);
} else {
result.success(null);
}
break;
case "getHitTestResult":
result.success(getHitTestResult());
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
...@@ -619,24 +631,11 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -619,24 +631,11 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
close(null); close(null);
} }
public byte[] takeScreenshot() { public void takeScreenshot(MethodChannel.Result result) {
if (webView != null) { if (webView != null)
Picture picture = webView.capturePicture(); webView.takeScreenshot(result);
Bitmap b = Bitmap.createBitmap( webView.getWidth(), else
webView.getHeight(), Bitmap.Config.ARGB_8888); result.success(null);
Canvas c = new Canvas(b);
picture.draw(c);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toByteArray();
}
return null;
} }
public void setOptions(InAppBrowserOptions newOptions, HashMap<String, Object> newOptionsMap) { public void setOptions(InAppBrowserOptions newOptions, HashMap<String, Object> newOptionsMap) {
...@@ -843,6 +842,25 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -843,6 +842,25 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
return null; return null;
} }
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void getSelectedText(MethodChannel.Result result) {
if (webView != null)
webView.getSelectedText(result);
else
result.success(null);
}
public Map<String, Object> getHitTestResult() {
if (webView != null) {
WebView.HitTestResult hitTestResult = webView.getHitTestResult();
Map<String, Object> obj = new HashMap<>();
obj.put("type", hitTestResult.getType());
obj.put("extra", hitTestResult.getExtra());
return obj;
}
return null;
}
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
if (webView != null) { if (webView != null) {
......
...@@ -70,7 +70,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler { ...@@ -70,7 +70,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
String url = (String) call.argument("url"); String url = (String) call.argument("url");
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options"); HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
Map<String, String> headers = (Map<String, String>) call.argument("headers"); Map<String, String> headers = (Map<String, String>) call.argument("headers");
openUrl(activity, uuid, url, options, headers); HashMap<String, Object> contextMenu = (HashMap<String, Object>) call.argument("contextMenu");
openUrl(activity, uuid, url, options, headers, contextMenu);
} }
result.success(true); result.success(true);
break; break;
...@@ -86,7 +87,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler { ...@@ -86,7 +87,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
} }
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options"); HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
Map<String, String> headers = (Map<String, String>) call.argument("headers"); Map<String, String> headers = (Map<String, String>) call.argument("headers");
openUrl(activity, uuid, url, options, headers); HashMap<String, Object> contextMenu = (HashMap<String, Object>) call.argument("contextMenu");
openUrl(activity, uuid, url, options, headers, contextMenu);
} }
result.success(true); result.success(true);
break; break;
...@@ -98,7 +100,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler { ...@@ -98,7 +100,8 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
String encoding = (String) call.argument("encoding"); String encoding = (String) call.argument("encoding");
String baseUrl = (String) call.argument("baseUrl"); String baseUrl = (String) call.argument("baseUrl");
String historyUrl = (String) call.argument("historyUrl"); String historyUrl = (String) call.argument("historyUrl");
openData(activity, uuid, options, data, mimeType, encoding, baseUrl, historyUrl); HashMap<String, Object> contextMenu = (HashMap<String, Object>) call.argument("contextMenu");
openData(activity, uuid, options, data, mimeType, encoding, baseUrl, historyUrl, contextMenu);
} }
result.success(true); result.success(true);
break; break;
...@@ -189,7 +192,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler { ...@@ -189,7 +192,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
} }
} }
public void openUrl(Activity activity, String uuid, String url, HashMap<String, Object> options, Map<String, String> headers) { public void openUrl(Activity activity, String uuid, String url, HashMap<String, Object> options, Map<String, String> headers, HashMap<String, Object> contextMenu) {
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString("fromActivity", activity.getClass().getName()); extras.putString("fromActivity", activity.getClass().getName());
extras.putString("url", url); extras.putString("url", url);
...@@ -197,10 +200,11 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler { ...@@ -197,10 +200,11 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
extras.putString("uuid", uuid); extras.putString("uuid", uuid);
extras.putSerializable("options", options); extras.putSerializable("options", options);
extras.putSerializable("headers", (Serializable) headers); extras.putSerializable("headers", (Serializable) headers);
extras.putSerializable("contextMenu", (Serializable) contextMenu);
startInAppBrowserActivity(activity, extras); startInAppBrowserActivity(activity, extras);
} }
public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl, String historyUrl) { public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl, String historyUrl, HashMap<String, Object> contextMenu) {
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putBoolean("isData", true); extras.putBoolean("isData", true);
extras.putString("uuid", uuid); extras.putString("uuid", uuid);
...@@ -210,6 +214,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler { ...@@ -210,6 +214,7 @@ public class InAppBrowserManager implements MethodChannel.MethodCallHandler {
extras.putString("encoding", encoding); extras.putString("encoding", encoding);
extras.putString("baseUrl", baseUrl); extras.putString("baseUrl", baseUrl);
extras.putString("historyUrl", historyUrl); extras.putString("historyUrl", historyUrl);
extras.putSerializable("contextMenu", (Serializable) contextMenu);
startInAppBrowserActivity(activity, extras); startInAppBrowserActivity(activity, extras);
} }
......
...@@ -4,6 +4,8 @@ import android.app.Activity; ...@@ -4,6 +4,8 @@ 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.Looper;
import android.util.Log; import android.util.Log;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import android.view.View; import android.view.View;
...@@ -49,15 +51,16 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -49,15 +51,16 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
displayListenerProxy.onPreWebViewInitialization(displayManager); displayListenerProxy.onPreWebViewInitialization(displayManager);
String initialUrl = (String) params.get("initialUrl"); String initialUrl = (String) params.get("initialUrl");
String initialFile = (String) params.get("initialFile"); final String initialFile = (String) params.get("initialFile");
Map<String, String> initialData = (Map<String, String>) params.get("initialData"); final Map<String, String> initialData = (Map<String, String>) params.get("initialData");
Map<String, String> initialHeaders = (Map<String, String>) params.get("initialHeaders"); final Map<String, String> initialHeaders = (Map<String, String>) params.get("initialHeaders");
HashMap<String, Object> initialOptions = (HashMap<String, Object>) params.get("initialOptions"); HashMap<String, Object> initialOptions = (HashMap<String, Object>) params.get("initialOptions");
HashMap<String, Object> contextMenu = (HashMap<String, Object>) params.get("contextMenu");
InAppWebViewOptions options = new InAppWebViewOptions(); InAppWebViewOptions options = new InAppWebViewOptions();
options.parse(initialOptions); options.parse(initialOptions);
webView = new InAppWebView(Shared.activity, this, id, options, containerView); webView = new InAppWebView(Shared.activity, this, id, options, contextMenu, containerView);
displayListenerProxy.onPostWebViewInitialization(displayManager); displayListenerProxy.onPostWebViewInitialization(displayManager);
// fix https://github.com/pichillilorenzo/flutter_inappwebview/issues/182 // fix https://github.com/pichillilorenzo/flutter_inappwebview/issues/182
...@@ -86,16 +89,23 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -86,16 +89,23 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
} }
} }
if (initialData != null) { final String finalInitialUrl = initialUrl;
String data = initialData.get("data"); Handler handler = new Handler(Looper.getMainLooper());
String mimeType = initialData.get("mimeType"); handler.post(new Runnable() {
String encoding = initialData.get("encoding"); @Override
String baseUrl = initialData.get("baseUrl"); public void run() {
String historyUrl = initialData.get("historyUrl"); if (initialData != null) {
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl); String data = initialData.get("data");
} String mimeType = initialData.get("mimeType");
else String encoding = initialData.get("encoding");
webView.loadUrl(initialUrl, initialHeaders); String baseUrl = initialData.get("baseUrl");
String historyUrl = initialData.get("historyUrl");
webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
}
else
webView.loadUrl(finalInitialUrl, initialHeaders);
}
});
if (containerView == null && id instanceof String) { if (containerView == null && id instanceof String) {
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
...@@ -381,6 +391,24 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -381,6 +391,24 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
case "getScale": case "getScale":
result.success((webView != null) ? webView.getUpdatedScale() : null); result.success((webView != null) ? webView.getUpdatedScale() : null);
break; break;
case "getSelectedText":
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.getSelectedText(result);
} else {
result.success(null);
}
break;
case "getHitTestResult":
if (webView != null) {
WebView.HitTestResult hitTestResult = webView.getHitTestResult();
Map<String, Object> obj = new HashMap<>();
obj.put("type", hitTestResult.getType());
obj.put("extra", hitTestResult.getExtra());
result.success(obj);
} else {
result.success(null);
}
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
......
...@@ -42,6 +42,7 @@ public class InAppWebViewOptions implements Options { ...@@ -42,6 +42,7 @@ public class InAppWebViewOptions implements Options {
public Boolean transparentBackground = false; public Boolean transparentBackground = false;
public Boolean disableVerticalScroll = false; public Boolean disableVerticalScroll = false;
public Boolean disableHorizontalScroll = false; public Boolean disableHorizontalScroll = false;
public Boolean disableContextMenu = false;
public Integer textZoom = 100; public Integer textZoom = 100;
public Boolean clearSessionCache = false; public Boolean clearSessionCache = false;
...@@ -165,6 +166,9 @@ public class InAppWebViewOptions implements Options { ...@@ -165,6 +166,9 @@ public class InAppWebViewOptions implements Options {
case "disableHorizontalScroll": case "disableHorizontalScroll":
disableHorizontalScroll = (Boolean) value; disableHorizontalScroll = (Boolean) value;
break; break;
case "disableContextMenu":
disableContextMenu = (Boolean) value;
break;
case "textZoom": case "textZoom":
textZoom = (Integer) value; textZoom = (Integer) value;
break; break;
...@@ -323,6 +327,7 @@ public class InAppWebViewOptions implements Options { ...@@ -323,6 +327,7 @@ public class InAppWebViewOptions implements Options {
options.put("transparentBackground", transparentBackground); options.put("transparentBackground", transparentBackground);
options.put("disableVerticalScroll", disableVerticalScroll); options.put("disableVerticalScroll", disableVerticalScroll);
options.put("disableHorizontalScroll", disableHorizontalScroll); options.put("disableHorizontalScroll", disableHorizontalScroll);
options.put("disableContextMenu", disableContextMenu);
options.put("textZoom", textZoom); options.put("textZoom", textZoom);
options.put("clearSessionCache", clearSessionCache); options.put("clearSessionCache", clearSessionCache);
options.put("builtInZoomControls", builtInZoomControls); options.put("builtInZoomControls", builtInZoomControls);
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dip"/>
<solid android:color="#FFF"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0"
android:background="@drawable/floating_action_mode_shape"
android:elevation="4dp">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"></LinearLayout>
</HorizontalScrollView>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="?android:attr/selectableItemBackground"
android:textColor="#000"
tools:text="Copy" />
\ No newline at end of file
{"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-11 15:01:02.801973","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/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"}
\ No newline at end of file \ No newline at end of file
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
# 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=lib/main.dart" export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/test_driver/app.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"
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios" export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1" export "FLUTTER_BUILD_NUMBER=1"
export "TRACK_WIDGET_CREATION=true"
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
...@@ -11,12 +13,33 @@ class InAppWebViewExampleScreen extends StatefulWidget { ...@@ -11,12 +13,33 @@ class InAppWebViewExampleScreen extends StatefulWidget {
class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
InAppWebViewController webView; InAppWebViewController webView;
ContextMenu contextMenu;
String url = ""; String url = "";
double progress = 0; double progress = 0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
contextMenu = ContextMenu(
onCreateContextMenu: (hitTestResult) async {
print("onCreateContextMenu");
print(hitTestResult.extra);
print(await webView.getSelectedText());
},
onHideContextMenu: () {
print("onHideContextMenu");
},
onContextMenuActionItemClicked: (contextMenuItemClicked) {
var id = (Platform.isAndroid) ? contextMenuItemClicked.androidId : contextMenuItemClicked.iosId;
print("onContextMenuActionItemClicked: " + id.toString() + " " + contextMenuItemClicked.title);
}
);
contextMenu.menuItems = [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!");
})
];
} }
@override @override
...@@ -49,12 +72,13 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -49,12 +72,13 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
decoration: decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)), BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView( child: InAppWebView(
initialUrl: "s", contextMenu: contextMenu,
initialUrl: "https://github.com/flutter",
// initialFile: "assets/index.html", // initialFile: "assets/index.html",
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewGroupOptions( initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true, debuggingEnabled: true
), ),
), ),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {
...@@ -106,7 +130,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -106,7 +130,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
setState(() { setState(() {
this.url = url; this.url = url;
}); });
}, }
), ),
), ),
), ),
......
final environment = {"NODE_SERVER_IP":"192.168.1.20"}; final environment = {"NODE_SERVER_IP":"192.168.1.21"};
\ No newline at end of file \ No newline at end of file
...@@ -38,11 +38,12 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin { ...@@ -38,11 +38,12 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
case "open": case "open":
let url = arguments!["url"] as! String let url = arguments!["url"] as! String
let options = arguments!["options"] as! [String: Any?] let options = arguments!["options"] as! [String: Any?]
let menuItemList = arguments!["menuItemList"] as! [[String: Any]]
let uuidFallback: String = arguments!["uuidFallback"] as! String let uuidFallback: String = arguments!["uuidFallback"] as! String
let headersFallback = arguments!["headersFallback"] as! [String: String] let headersFallback = arguments!["headersFallback"] as! [String: String]
let optionsFallback = arguments!["optionsFallback"] as! [String: Any?] let optionsFallback = arguments!["optionsFallback"] as! [String: Any?]
let menuItemList = arguments!["menuItemList"] as! [[String: Any]] let contextMenuFallback = arguments!["contextMenuFallback"] as! [String: Any]
open(uuid: uuid, url: url, options: options, uuidFallback: uuidFallback, headersFallback: headersFallback, optionsFallback: optionsFallback, menuItemList: menuItemList, result: result) open(uuid: uuid, url: url, options: options, menuItemList: menuItemList, uuidFallback: uuidFallback, headersFallback: headersFallback, optionsFallback: optionsFallback, contextMenuFallback: contextMenuFallback, result: result)
break break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
...@@ -50,7 +51,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin { ...@@ -50,7 +51,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
} }
} }
public func open(uuid: String, url: String, options: [String: Any?], uuidFallback: String?, headersFallback: [String: String], optionsFallback: [String: Any?], menuItemList: [[String: Any]], result: @escaping FlutterResult) { public func open(uuid: String, url: String, options: [String: Any?], menuItemList: [[String: Any]], uuidFallback: String, headersFallback: [String: String], optionsFallback: [String: Any?], contextMenuFallback: [String: Any], result: @escaping FlutterResult) {
let absoluteUrl = URL(string: url)!.absoluteURL let absoluteUrl = URL(string: url)!.absoluteURL
if self.previousStatusBarStyle == -1 { if self.previousStatusBarStyle == -1 {
...@@ -105,7 +106,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin { ...@@ -105,7 +106,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
return return
} }
SwiftFlutterPlugin.instance!.inAppBrowserManager!.openUrl(uuid: uuidFallback!, url: url, options: optionsFallback, headers: headersFallback) SwiftFlutterPlugin.instance!.inAppBrowserManager!.openUrl(uuid: uuidFallback, url: url, options: optionsFallback, headers: headersFallback, contextMenu: contextMenuFallback)
} }
} }
} }
...@@ -38,12 +38,13 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor ...@@ -38,12 +38,13 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
let initialData = args["initialData"] as? [String: String] let initialData = args["initialData"] as? [String: String]
let initialHeaders = args["initialHeaders"] as? [String: String] let initialHeaders = args["initialHeaders"] as? [String: String]
let initialOptions = args["initialOptions"] as! [String: Any?] let initialOptions = args["initialOptions"] as! [String: Any?]
let contextMenu = args["contextMenu"] as? [String: Any]
let options = InAppWebViewOptions() let options = InAppWebViewOptions()
let _ = options.parse(options: initialOptions) let _ = options.parse(options: initialOptions)
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: options) let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: options)
webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, channel: channel!) webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, contextMenu: contextMenu, channel: channel!)
webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight] webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
myView!.autoresizesSubviews = true myView!.autoresizesSubviews = true
myView!.autoresizingMask = [.flexibleWidth, .flexibleHeight] myView!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
...@@ -98,7 +99,7 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor ...@@ -98,7 +99,7 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
deinit { deinit {
print("FlutterWebViewController - dealloc") print("FlutterWebViewController - dealloc")
channel?.setMethodCallHandler(nil) channel?.setMethodCallHandler(nil)
webView!.dispose() webView?.dispose()
webView = nil webView = nil
myView = nil myView = nil
} }
...@@ -373,7 +374,8 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor ...@@ -373,7 +374,8 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
case "printCurrentPage": case "printCurrentPage":
if webView != nil { if webView != nil {
webView!.printCurrentPage(printCompletionHandler: {(completed, error) in webView!.printCurrentPage(printCompletionHandler: {(completed, error) in
if !completed, let _ = error { if !completed, let err = error {
print(err.localizedDescription)
result(false) result(false)
return return
} }
...@@ -398,6 +400,32 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor ...@@ -398,6 +400,32 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
case "hasOnlySecureContent": case "hasOnlySecureContent":
result( (webView != nil) ? webView!.hasOnlySecureContent : nil ) result( (webView != nil) ? webView!.hasOnlySecureContent : nil )
break break
case "getSelectedText":
if webView != nil {
webView!.getSelectedText { (value, error) in
if let err = error {
print(err.localizedDescription)
}
result(value)
}
}
else {
result(nil)
}
break
case "getHitTestResult":
if webView != nil {
webView!.getHitTestResult { (value, error) in
if let err = error {
print(err.localizedDescription)
}
result(value)
}
}
else {
result(nil)
}
break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
break break
......
...@@ -41,7 +41,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -41,7 +41,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
let url = arguments!["url"] as! String let url = arguments!["url"] as! String
let options = arguments!["options"] as! [String: Any?] let options = arguments!["options"] as! [String: Any?]
let headers = arguments!["headers"] as! [String: String] let headers = arguments!["headers"] as! [String: String]
openUrl(uuid: uuid, url: url, options: options, headers: headers) let contextMenu = arguments!["contextMenu"] as! [String: Any]
openUrl(uuid: uuid, url: url, options: options, headers: headers, contextMenu: contextMenu)
result(true) result(true)
break break
case "openFile": case "openFile":
...@@ -56,7 +57,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -56,7 +57,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
} }
let options = arguments!["options"] as! [String: Any?] let options = arguments!["options"] as! [String: Any?]
let headers = arguments!["headers"] as! [String: String] let headers = arguments!["headers"] as! [String: String]
openUrl(uuid: uuid, url: url, options: options, headers: headers) let contextMenu = arguments!["contextMenu"] as! [String: Any]
openUrl(uuid: uuid, url: url, options: options, headers: headers, contextMenu: contextMenu)
result(true) result(true)
break break
case "openData": case "openData":
...@@ -65,7 +67,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -65,7 +67,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
let mimeType = arguments!["mimeType"] as! String let mimeType = arguments!["mimeType"] as! String
let encoding = arguments!["encoding"] as! String let encoding = arguments!["encoding"] as! String
let baseUrl = arguments!["baseUrl"] as! String let baseUrl = arguments!["baseUrl"] as! String
openData(uuid: uuid, options: options, data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl) let contextMenu = arguments!["contextMenu"] as! [String: Any]
openData(uuid: uuid, options: options, data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl, contextMenu: contextMenu)
result(true) result(true)
break break
case "openWithSystemBrowser": case "openWithSystemBrowser":
...@@ -110,7 +113,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -110,7 +113,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
return webViewController return webViewController
} }
public func openUrl(uuid: String, url: String, options: [String: Any?], headers: [String: String]) { public func openUrl(uuid: String, url: String, options: [String: Any?], headers: [String: String], contextMenu: [String: Any]) {
let absoluteUrl = URL(string: url)!.absoluteURL let absoluteUrl = URL(string: url)!.absoluteURL
let webViewController = prepareInAppBrowserWebViewController(options: options) let webViewController = prepareInAppBrowserWebViewController(options: options)
...@@ -119,6 +122,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -119,6 +122,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
webViewController.tmpWindow = tmpWindow webViewController.tmpWindow = tmpWindow
webViewController.initURL = absoluteUrl webViewController.initURL = absoluteUrl
webViewController.initHeaders = headers webViewController.initHeaders = headers
webViewController.contextMenu = contextMenu
if webViewController.isHidden { if webViewController.isHidden {
webViewController.view.isHidden = true webViewController.view.isHidden = true
...@@ -137,7 +141,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -137,7 +141,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
} }
} }
public func openData(uuid: String, options: [String: Any?], data: String, mimeType: String, encoding: String, baseUrl: String) { public func openData(uuid: String, options: [String: Any?], data: String, mimeType: String, encoding: String, baseUrl: String, contextMenu: [String: Any]) {
let webViewController = prepareInAppBrowserWebViewController(options: options) let webViewController = prepareInAppBrowserWebViewController(options: options)
webViewController.uuid = uuid webViewController.uuid = uuid
...@@ -146,6 +150,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin { ...@@ -146,6 +150,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
webViewController.initMimeType = mimeType webViewController.initMimeType = mimeType
webViewController.initEncoding = encoding webViewController.initEncoding = encoding
webViewController.initBaseUrl = baseUrl webViewController.initBaseUrl = baseUrl
webViewController.contextMenu = contextMenu
if webViewController.isHidden { if webViewController.isHidden {
webViewController.view.isHidden = true webViewController.view.isHidden = true
......
...@@ -17,7 +17,7 @@ typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, B ...@@ -17,7 +17,7 @@ typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, B
public class InAppWebView_IBWrapper: InAppWebView { public class InAppWebView_IBWrapper: InAppWebView {
required init(coder: NSCoder) { required init(coder: NSCoder) {
let config = WKWebViewConfiguration() let config = WKWebViewConfiguration()
super.init(frame: .zero, configuration: config, IABController: nil, channel: nil) super.init(frame: .zero, configuration: config, IABController: nil, contextMenu: nil, channel: nil)
self.translatesAutoresizingMaskIntoConstraints = false self.translatesAutoresizingMaskIntoConstraints = false
} }
} }
...@@ -46,6 +46,7 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS ...@@ -46,6 +46,7 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
var webView: InAppWebView! var webView: InAppWebView!
var channel: FlutterMethodChannel? var channel: FlutterMethodChannel?
var initURL: URL? var initURL: URL?
var contextMenu: [String: Any]?
var tmpWindow: UIWindow? var tmpWindow: UIWindow?
var browserOptions: InAppBrowserOptions? var browserOptions: InAppBrowserOptions?
var webViewOptions: InAppWebViewOptions? var webViewOptions: InAppWebViewOptions?
...@@ -281,6 +282,32 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS ...@@ -281,6 +282,32 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
case "hasOnlySecureContent": case "hasOnlySecureContent":
result(webView.hasOnlySecureContent) result(webView.hasOnlySecureContent)
break break
case "getSelectedText":
if webView != nil {
webView!.getSelectedText { (value, error) in
if let err = error {
print(err.localizedDescription)
}
result(value)
}
}
else {
result(nil)
}
break
case "getHitTestResult":
if webView != nil {
webView!.getHitTestResult { (value, error) in
if let err = error {
print(err.localizedDescription)
}
result(value)
}
}
else {
result(nil)
}
break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
break break
...@@ -290,7 +317,7 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS ...@@ -290,7 +317,7 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
public override func viewWillAppear(_ animated: Bool) { public override func viewWillAppear(_ animated: Bool) {
if !viewPrepared { if !viewPrepared {
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: webViewOptions) let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: webViewOptions)
self.webView = InAppWebView(frame: .zero, configuration: preWebviewConfiguration, IABController: self, channel: channel!) self.webView = InAppWebView(frame: .zero, configuration: preWebviewConfiguration, IABController: self, contextMenu: contextMenu, channel: channel!)
self.containerWebView.addSubview(self.webView) self.containerWebView.addSubview(self.webView)
prepareConstraints() prepareConstraints()
prepareWebView() prepareWebView()
...@@ -685,7 +712,8 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS ...@@ -685,7 +712,8 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0) tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
UIApplication.shared.delegate?.window??.makeKeyAndVisible() UIApplication.shared.delegate?.window??.makeKeyAndVisible()
onExit() onExit()
channel!.setMethodCallHandler(nil) channel?.setMethodCallHandler(nil)
channel = nil
} }
public func onBrowserCreated() { public func onBrowserCreated() {
......
This diff is collapsed.
...@@ -33,6 +33,7 @@ public class InAppWebViewOptions: Options { ...@@ -33,6 +33,7 @@ public class InAppWebViewOptions: Options {
var transparentBackground = false var transparentBackground = false
var disableVerticalScroll = false var disableVerticalScroll = false
var disableHorizontalScroll = false var disableHorizontalScroll = false
var disableContextMenu = false
var disallowOverScroll = false var disallowOverScroll = false
var enableViewportScale = false var enableViewportScale = false
......
...@@ -31,11 +31,10 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa ...@@ -31,11 +31,10 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
} }
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary // let arguments = call.arguments as? NSDictionary
switch call.method { switch call.method {
case "close": case "close":
close() close(result: result)
break break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
...@@ -67,7 +66,7 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa ...@@ -67,7 +66,7 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (safariOptions?.transitionStyle)!)! self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (safariOptions?.transitionStyle)!)!
} }
func close() { func close(result: FlutterResult?) {
dismiss(animated: true) dismiss(animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in
...@@ -75,11 +74,14 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa ...@@ -75,11 +74,14 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
UIApplication.shared.delegate?.window??.makeKeyAndVisible() UIApplication.shared.delegate?.window??.makeKeyAndVisible()
self.onChromeSafariBrowserClosed() self.onChromeSafariBrowserClosed()
self.dispose() self.dispose()
if result != nil {
result!(true)
}
}) })
} }
public func safariViewControllerDidFinish(_ controller: SFSafariViewController) { public func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
close() close(result: nil)
} }
public func safariViewController(_ controller: SFSafariViewController, public func safariViewController(_ controller: SFSafariViewController,
......
...@@ -35,3 +35,4 @@ export 'src/webview_options.dart'; ...@@ -35,3 +35,4 @@ export 'src/webview_options.dart';
export 'src/content_blocker.dart'; export 'src/content_blocker.dart';
export 'src/http_auth_credentials_database.dart'; export 'src/http_auth_credentials_database.dart';
export 'src/web_storage_manager.dart'; export 'src/web_storage_manager.dart';
export 'src/context_menu.dart';
...@@ -61,6 +61,8 @@ class ChromeSafariBrowser { ...@@ -61,6 +61,8 @@ class ChromeSafariBrowser {
///[headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value. ///[headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value.
/// ///
///[optionsFallback]: Options used by the [InAppBrowser] instance fallback. ///[optionsFallback]: Options used by the [InAppBrowser] instance fallback.
///
///[contextMenuFallback]: Context Menu used by the [InAppBrowser] instance fallback.
Future<void> open( Future<void> open(
{@required String url, {@required String url,
ChromeSafariBrowserClassOptions options, ChromeSafariBrowserClassOptions options,
...@@ -81,11 +83,12 @@ class ChromeSafariBrowser { ...@@ -81,11 +83,12 @@ class ChromeSafariBrowser {
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url); args.putIfAbsent('url', () => url);
args.putIfAbsent('options', () => options?.toMap() ?? {}); args.putIfAbsent('options', () => options?.toMap() ?? {});
args.putIfAbsent('menuItemList', () => menuItemList);
args.putIfAbsent('uuidFallback', args.putIfAbsent('uuidFallback',
() => (browserFallback != null) ? browserFallback.uuid : ''); () => (browserFallback != null) ? browserFallback.uuid : '');
args.putIfAbsent('headersFallback', () => headersFallback); args.putIfAbsent('headersFallback', () => headersFallback);
args.putIfAbsent('optionsFallback', () => optionsFallback?.toMap() ?? {}); args.putIfAbsent('optionsFallback', () => optionsFallback?.toMap() ?? {});
args.putIfAbsent('menuItemList', () => menuItemList); args.putIfAbsent('contextMenuFallback', () => browserFallback?.contextMenu?.toMap() ?? {});
await _sharedChannel.invokeMethod('open', args); await _sharedChannel.invokeMethod('open', args);
this._isOpened = true; this._isOpened = true;
} }
......
import 'package:flutter/foundation.dart';
import 'package:flutter_inappwebview/src/webview.dart';
import 'types.dart';
///Class that represents the WebView context menu. It used by [WebView.contextMenu].
///
///**NOTE**: To make it work properly on Android, JavaScript should be enabled!
class ContextMenu {
///Event fired when the context menu for this WebView is being built.
///
///[hitTestResult] represents the hit result for hitting an HTML elements.
final void Function(InAppWebViewHitTestResult hitTestResult) onCreateContextMenu;
///Event fired when the context menu for this WebView is being hidden.
final void Function() onHideContextMenu;
///Event fired when a context menu item has been clicked.
///
///[contextMenuItemClicked] represents the [ContextMenuItem] clicked.
final void Function(ContextMenuItem contextMenuItemClicked) onContextMenuActionItemClicked;
///List of the custom [ContextMenuItem].
List<ContextMenuItem> menuItems = List();
ContextMenu({
this.menuItems,
this.onCreateContextMenu,
this.onHideContextMenu,
this.onContextMenuActionItemClicked
});
Map<String, dynamic> toMap() {
return {
"menuItems": menuItems.map((menuItem) => menuItem?.toMap()).toList()
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
}
///Class that represent an item of the [ContextMenu].
class ContextMenuItem {
///Android menu item ID.
int androidId;
///iOS menu item ID.
String iosId;
///Menu item title.
String title;
///Menu item action that will be called when an user clicks on it.
Function() action;
ContextMenuItem({@required this.androidId, @required this.iosId, @required this.title, this.action});
Map<String, dynamic> toMap() {
return {
"androidId": androidId,
"iosId": iosId,
"title": title
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
}
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'context_menu.dart';
import 'types.dart'; import 'types.dart';
import 'webview.dart'; import 'webview.dart';
import 'in_app_webview_controller.dart'; import 'in_app_webview_controller.dart';
...@@ -16,46 +17,48 @@ class HeadlessInAppWebView implements WebView { ...@@ -16,46 +17,48 @@ class HeadlessInAppWebView implements WebView {
///WebView Controller that can be used to access the [InAppWebViewController] API. ///WebView Controller that can be used to access the [InAppWebViewController] API.
InAppWebViewController webViewController; InAppWebViewController webViewController;
HeadlessInAppWebView( HeadlessInAppWebView({
{this.onWebViewCreated, this.onWebViewCreated,
this.onLoadStart, this.onLoadStart,
this.onLoadStop, this.onLoadStop,
this.onLoadError, this.onLoadError,
this.onLoadHttpError, this.onLoadHttpError,
this.onProgressChanged, this.onProgressChanged,
this.onConsoleMessage, this.onConsoleMessage,
this.shouldOverrideUrlLoading, this.shouldOverrideUrlLoading,
this.onLoadResource, this.onLoadResource,
this.onScrollChanged, this.onScrollChanged,
this.onDownloadStart, this.onDownloadStart,
this.onLoadResourceCustomScheme, this.onLoadResourceCustomScheme,
this.onCreateWindow, this.onCreateWindow,
this.onJsAlert, this.onJsAlert,
this.onJsConfirm, this.onJsConfirm,
this.onJsPrompt, this.onJsPrompt,
this.onReceivedHttpAuthRequest, this.onReceivedHttpAuthRequest,
this.onReceivedServerTrustAuthRequest, this.onReceivedServerTrustAuthRequest,
this.onReceivedClientCertRequest, this.onReceivedClientCertRequest,
this.onFindResultReceived, this.onFindResultReceived,
this.shouldInterceptAjaxRequest, this.shouldInterceptAjaxRequest,
this.onAjaxReadyStateChange, this.onAjaxReadyStateChange,
this.onAjaxProgress, this.onAjaxProgress,
this.shouldInterceptFetchRequest, this.shouldInterceptFetchRequest,
this.onUpdateVisitedHistory, this.onUpdateVisitedHistory,
this.onPrint, this.onPrint,
this.onLongPressHitTestResult, this.onLongPressHitTestResult,
this.androidOnSafeBrowsingHit, this.androidOnSafeBrowsingHit,
this.androidOnPermissionRequest, this.androidOnPermissionRequest,
this.androidOnGeolocationPermissionsShowPrompt, this.androidOnGeolocationPermissionsShowPrompt,
this.androidOnGeolocationPermissionsHidePrompt, this.androidOnGeolocationPermissionsHidePrompt,
this.iosOnWebContentProcessDidTerminate, this.iosOnWebContentProcessDidTerminate,
this.iosOnDidCommit, this.iosOnDidCommit,
this.iosOnDidReceiveServerRedirectForProvisionalNavigation, this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
this.initialUrl, this.initialUrl,
this.initialFile, this.initialFile,
this.initialData, this.initialData,
this.initialHeaders, this.initialHeaders,
this.initialOptions}) { this.initialOptions,
this.contextMenu
}) {
uuid = uuidGenerator.v4(); uuid = uuidGenerator.v4();
webViewController = new InAppWebViewController(uuid, this); webViewController = new InAppWebViewController(uuid, this);
} }
...@@ -83,7 +86,8 @@ class HeadlessInAppWebView implements WebView { ...@@ -83,7 +86,8 @@ class HeadlessInAppWebView implements WebView {
'initialFile': this.initialFile, 'initialFile': this.initialFile,
'initialData': this.initialData?.toMap(), 'initialData': this.initialData?.toMap(),
'initialHeaders': this.initialHeaders, 'initialHeaders': this.initialHeaders,
'initialOptions': this.initialOptions?.toMap() 'initialOptions': this.initialOptions?.toMap(),
'contextMenu': this.contextMenu?.toMap() ?? {}
}); });
await _sharedChannel.invokeMethod('createHeadlessWebView', args); await _sharedChannel.invokeMethod('createHeadlessWebView', args);
} }
...@@ -130,6 +134,9 @@ class HeadlessInAppWebView implements WebView { ...@@ -130,6 +134,9 @@ class HeadlessInAppWebView implements WebView {
@override @override
final InAppWebViewGroupOptions initialOptions; final InAppWebViewGroupOptions initialOptions;
@override
final ContextMenu contextMenu;
@override @override
final String initialUrl; final String initialUrl;
...@@ -210,7 +217,7 @@ class HeadlessInAppWebView implements WebView { ...@@ -210,7 +217,7 @@ class HeadlessInAppWebView implements WebView {
@override @override
final void Function(InAppWebViewController controller, final void Function(InAppWebViewController controller,
LongPressHitTestResult hitTestResult) onLongPressHitTestResult; InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
@override @override
final void Function(InAppWebViewController controller, String url) onPrint; final void Function(InAppWebViewController controller, String url) onPrint;
......
...@@ -4,6 +4,7 @@ import 'dart:io'; ...@@ -4,6 +4,7 @@ import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'context_menu.dart';
import 'in_app_webview_controller.dart'; import 'in_app_webview_controller.dart';
import 'webview_options.dart'; import 'webview_options.dart';
...@@ -12,7 +13,12 @@ import 'types.dart'; ...@@ -12,7 +13,12 @@ import 'types.dart';
///This class uses the native WebView of the platform. ///This class uses the native WebView of the platform.
///The [webViewController] field can be used to access the [InAppWebViewController] API. ///The [webViewController] field can be used to access the [InAppWebViewController] API.
class InAppBrowser { class InAppBrowser {
///Browser's UUID
String uuid; String uuid;
///Context menu used by the browser
ContextMenu contextMenu;
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
HashMap<String, JavaScriptHandlerCallback>(); HashMap<String, JavaScriptHandlerCallback>();
bool _isOpened = false; bool _isOpened = false;
...@@ -67,6 +73,7 @@ class InAppBrowser { ...@@ -67,6 +73,7 @@ class InAppBrowser {
args.putIfAbsent('url', () => url); args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers); args.putIfAbsent('headers', () => headers);
args.putIfAbsent('options', () => options?.toMap() ?? {}); args.putIfAbsent('options', () => options?.toMap() ?? {});
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
await _sharedChannel.invokeMethod('openUrl', args); await _sharedChannel.invokeMethod('openUrl', args);
} }
...@@ -117,6 +124,7 @@ class InAppBrowser { ...@@ -117,6 +124,7 @@ class InAppBrowser {
args.putIfAbsent('url', () => assetFilePath); args.putIfAbsent('url', () => assetFilePath);
args.putIfAbsent('headers', () => headers); args.putIfAbsent('headers', () => headers);
args.putIfAbsent('options', () => options?.toMap() ?? {}); args.putIfAbsent('options', () => options?.toMap() ?? {});
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
await _sharedChannel.invokeMethod('openFile', args); await _sharedChannel.invokeMethod('openFile', args);
} }
...@@ -146,6 +154,7 @@ class InAppBrowser { ...@@ -146,6 +154,7 @@ class InAppBrowser {
args.putIfAbsent('encoding', () => encoding); args.putIfAbsent('encoding', () => encoding);
args.putIfAbsent('baseUrl', () => baseUrl); args.putIfAbsent('baseUrl', () => baseUrl);
args.putIfAbsent('historyUrl', () => androidHistoryUrl); args.putIfAbsent('historyUrl', () => androidHistoryUrl);
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
await _sharedChannel.invokeMethod('openData', args); await _sharedChannel.invokeMethod('openData', args);
} }
...@@ -429,7 +438,7 @@ class InAppBrowser { ...@@ -429,7 +438,7 @@ class InAppBrowser {
///Event fired when an HTML element of the webview has been clicked and held. ///Event fired when an HTML element of the webview has been clicked and held.
/// ///
///[hitTestResult] represents the hit result for hitting an HTML elements. ///[hitTestResult] represents the hit result for hitting an HTML elements.
void onLongPressHitTestResult(LongPressHitTestResult hitTestResult) {} void onLongPressHitTestResult(InAppWebViewHitTestResult hitTestResult) {}
///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing. ///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible. ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
......
...@@ -6,6 +6,7 @@ import 'package:flutter/services.dart'; ...@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'context_menu.dart';
import 'webview.dart'; import 'webview.dart';
import 'types.dart'; import 'types.dart';
import 'in_app_webview_controller.dart'; import 'in_app_webview_controller.dart';
...@@ -38,6 +39,7 @@ class InAppWebView extends StatefulWidget implements WebView { ...@@ -38,6 +39,7 @@ class InAppWebView extends StatefulWidget implements WebView {
this.initialData, this.initialData,
this.initialHeaders = const {}, this.initialHeaders = const {},
@required this.initialOptions, @required this.initialOptions,
this.contextMenu,
this.onWebViewCreated, this.onWebViewCreated,
this.onLoadStart, this.onLoadStart,
this.onLoadStop, this.onLoadStop,
...@@ -112,6 +114,9 @@ class InAppWebView extends StatefulWidget implements WebView { ...@@ -112,6 +114,9 @@ class InAppWebView extends StatefulWidget implements WebView {
@override @override
final String initialUrl; final String initialUrl;
@override
final ContextMenu contextMenu;
@override @override
final Future<void> Function(InAppWebViewController controller) iosOnDidCommit; final Future<void> Function(InAppWebViewController controller) iosOnDidCommit;
...@@ -189,7 +194,7 @@ class InAppWebView extends StatefulWidget implements WebView { ...@@ -189,7 +194,7 @@ class InAppWebView extends StatefulWidget implements WebView {
@override @override
final void Function(InAppWebViewController controller, final void Function(InAppWebViewController controller,
LongPressHitTestResult hitTestResult) onLongPressHitTestResult; InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
@override @override
final void Function(InAppWebViewController controller, String url) onPrint; final void Function(InAppWebViewController controller, String url) onPrint;
...@@ -258,7 +263,8 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -258,7 +263,8 @@ class _InAppWebViewState extends State<InAppWebView> {
'initialFile': widget.initialFile, 'initialFile': widget.initialFile,
'initialData': widget.initialData?.toMap(), 'initialData': widget.initialData?.toMap(),
'initialHeaders': widget.initialHeaders, 'initialHeaders': widget.initialHeaders,
'initialOptions': widget.initialOptions?.toMap() ?? {} 'initialOptions': widget.initialOptions?.toMap() ?? {},
'contextMenu': widget.contextMenu?.toMap() ?? {}
}, },
creationParamsCodec: const StandardMessageCodec(), creationParamsCodec: const StandardMessageCodec(),
); );
...@@ -291,7 +297,8 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -291,7 +297,8 @@ class _InAppWebViewState extends State<InAppWebView> {
'initialFile': widget.initialFile, 'initialFile': widget.initialFile,
'initialData': widget.initialData?.toMap(), 'initialData': widget.initialData?.toMap(),
'initialHeaders': widget.initialHeaders, 'initialHeaders': widget.initialHeaders,
'initialOptions': widget.initialOptions?.toMap() ?? {} 'initialOptions': widget.initialOptions?.toMap() ?? {},
'contextMenu': widget.contextMenu?.toMap() ?? {}
}, },
creationParamsCodec: const StandardMessageCodec(), creationParamsCodec: const StandardMessageCodec(),
); );
......
...@@ -346,12 +346,12 @@ class InAppWebViewController { ...@@ -346,12 +346,12 @@ class InAppWebViewController {
_webview.iosOnWebContentProcessDidTerminate(this); _webview.iosOnWebContentProcessDidTerminate(this);
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
_inAppBrowser.iosOnWebContentProcessDidTerminate(); _inAppBrowser.iosOnWebContentProcessDidTerminate();
return null; break;
case "onDidCommit": case "onDidCommit":
if (_webview != null && _webview.iosOnDidCommit != null) if (_webview != null && _webview.iosOnDidCommit != null)
_webview.iosOnDidCommit(this); _webview.iosOnDidCommit(this);
else if (_inAppBrowser != null) _inAppBrowser.iosOnDidCommit(); else if (_inAppBrowser != null) _inAppBrowser.iosOnDidCommit();
return null; break;
case "onDidReceiveServerRedirectForProvisionalNavigation": case "onDidReceiveServerRedirectForProvisionalNavigation":
if (_webview != null && if (_webview != null &&
_webview.iosOnDidReceiveServerRedirectForProvisionalNavigation != _webview.iosOnDidReceiveServerRedirectForProvisionalNavigation !=
...@@ -359,21 +359,80 @@ class InAppWebViewController { ...@@ -359,21 +359,80 @@ class InAppWebViewController {
_webview.iosOnDidReceiveServerRedirectForProvisionalNavigation(this); _webview.iosOnDidReceiveServerRedirectForProvisionalNavigation(this);
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
_inAppBrowser.iosOnDidReceiveServerRedirectForProvisionalNavigation(); _inAppBrowser.iosOnDidReceiveServerRedirectForProvisionalNavigation();
return null; break;
case "onLongPressHitTestResult": case "onLongPressHitTestResult":
Map<dynamic, dynamic> hitTestResultMap = Map<dynamic, dynamic> hitTestResultMap =
call.arguments["hitTestResult"]; call.arguments["hitTestResult"];
LongPressHitTestResultType type = LongPressHitTestResultType.fromValue( InAppWebViewHitTestResultType type = InAppWebViewHitTestResultType.fromValue(
hitTestResultMap["type"].toInt()); hitTestResultMap["type"].toInt());
String extra = hitTestResultMap["extra"]; String extra = hitTestResultMap["extra"];
LongPressHitTestResult hitTestResult = InAppWebViewHitTestResult hitTestResult = InAppWebViewHitTestResult(type: type, extra: extra);
new LongPressHitTestResult(type: type, extra: extra);
if (_webview != null && _webview.onLongPressHitTestResult != null) if (_webview != null && _webview.onLongPressHitTestResult != null)
_webview.onLongPressHitTestResult(this, hitTestResult); _webview.onLongPressHitTestResult(this, hitTestResult);
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
_inAppBrowser.onLongPressHitTestResult(hitTestResult); _inAppBrowser.onLongPressHitTestResult(hitTestResult);
break; break;
case "onCreateContextMenu":
ContextMenu contextMenu;
if (_webview != null && _webview.contextMenu != null) {
contextMenu = _webview.contextMenu;
} else if (_inAppBrowser != null && _inAppBrowser.contextMenu != null) {
contextMenu = _inAppBrowser.contextMenu;
}
if (contextMenu != null && contextMenu.onCreateContextMenu != null) {
Map<dynamic, dynamic> hitTestResultMap =
call.arguments["hitTestResult"];
InAppWebViewHitTestResultType type = InAppWebViewHitTestResultType.fromValue(
hitTestResultMap["type"].toInt());
String extra = hitTestResultMap["extra"];
InAppWebViewHitTestResult hitTestResult = InAppWebViewHitTestResult(type: type, extra: extra);
contextMenu.onCreateContextMenu(hitTestResult);
}
break;
case "onHideContextMenu":
ContextMenu contextMenu;
if (_webview != null && _webview.contextMenu != null) {
contextMenu = _webview.contextMenu;
} else if (_inAppBrowser != null && _inAppBrowser.contextMenu != null) {
contextMenu = _inAppBrowser.contextMenu;
}
if (contextMenu != null && contextMenu.onHideContextMenu != null) {
contextMenu.onHideContextMenu();
}
break;
case "onContextMenuActionItemClicked":
ContextMenu contextMenu;
if (_webview != null && _webview.contextMenu != null) {
contextMenu = _webview.contextMenu;
} else if (_inAppBrowser != null && _inAppBrowser.contextMenu != null) {
contextMenu = _inAppBrowser.contextMenu;
}
if (contextMenu != null) {
int androidId = call.arguments["androidId"];
String iosId = call.arguments["iosId"];
String title = call.arguments["title"];
ContextMenuItem menuItemClicked = ContextMenuItem(androidId: androidId, iosId: iosId, title: title, action: null);
for (var menuItem in contextMenu.menuItems) {
if ((Platform.isAndroid && menuItem.androidId == androidId) ||
(Platform.isIOS && menuItem.iosId == iosId)) {
menuItemClicked = menuItem;
menuItem?.action();
break;
}
}
if (contextMenu.onContextMenuActionItemClicked != null) {
contextMenu.onContextMenuActionItemClicked(menuItemClicked);
}
}
break;
case "onCallJsHandler": case "onCallJsHandler":
String handlerName = call.arguments["handlerName"]; String handlerName = call.arguments["handlerName"];
// decode args to json // decode args to json
...@@ -1198,7 +1257,7 @@ class InAppWebViewController { ...@@ -1198,7 +1257,7 @@ class InAppWebViewController {
return await _channel.invokeMethod('getContentHeight', args); return await _channel.invokeMethod('getContentHeight', args);
} }
///Gets the height of the HTML content. ///Performs a zoom operation in this WebView.
/// ///
///[zoomFactor] represents the zoom factor to apply. On Android, the zoom factor will be clamped to the Webview's zoom limits and, also, this value must be in the range 0.01 to 100.0 inclusive. ///[zoomFactor] represents the zoom factor to apply. On Android, the zoom factor will be clamped to the Webview's zoom limits and, also, this value must be in the range 0.01 to 100.0 inclusive.
/// ///
...@@ -1215,6 +1274,27 @@ class InAppWebViewController { ...@@ -1215,6 +1274,27 @@ class InAppWebViewController {
return await _channel.invokeMethod('getScale', args); return await _channel.invokeMethod('getScale', args);
} }
///Gets the selected text.
///
///**NOTE**: This method is implemented with using JavaScript.
///Available only on Android 19+.
Future<String> getSelectedText() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _channel.invokeMethod('getSelectedText', args);
}
///Gets the hit result for hitting an HTML elements.
///
///**NOTE**: On iOS it is implemented using JavaScript.
Future<InAppWebViewHitTestResult> getHitTestResult() async {
Map<String, dynamic> args = <String, dynamic>{};
var hitTestResultMap = await _channel.invokeMethod('getHitTestResult', args);
InAppWebViewHitTestResultType type = InAppWebViewHitTestResultType.fromValue(
hitTestResultMap["type"].toInt());
String extra = hitTestResultMap["extra"];
return InAppWebViewHitTestResult(type: type, extra: extra);
}
///Gets the default user agent. ///Gets the default user agent.
static Future<String> getDefaultUserAgent() async { static Future<String> getDefaultUserAgent() async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
......
...@@ -2297,13 +2297,13 @@ class IOSWKWebsiteDataRecord { ...@@ -2297,13 +2297,13 @@ class IOSWKWebsiteDataRecord {
} }
} }
///Class representing the [LongPressHitTestResult] type. ///Class representing the [InAppWebViewHitTestResult] type.
class LongPressHitTestResultType { class InAppWebViewHitTestResultType {
final int _value; final int _value;
const LongPressHitTestResultType._internal(this._value); const InAppWebViewHitTestResultType._internal(this._value);
static LongPressHitTestResultType fromValue(int value) { static InAppWebViewHitTestResultType fromValue(int value) {
if (value != null && [0, 2, 3, 4, 5, 7, 8, 9].contains(value)) if (value != null && [0, 2, 3, 4, 5, 7, 8, 9].contains(value))
return LongPressHitTestResultType._internal(value); return InAppWebViewHitTestResultType._internal(value);
return null; return null;
} }
...@@ -2331,22 +2331,22 @@ class LongPressHitTestResultType { ...@@ -2331,22 +2331,22 @@ class LongPressHitTestResultType {
} }
} }
///Default [LongPressHitTestResult], where the target is unknown. ///Default [InAppWebViewHitTestResult], where the target is unknown.
static const UNKNOWN_TYPE = const LongPressHitTestResultType._internal(0); static const UNKNOWN_TYPE = const InAppWebViewHitTestResultType._internal(0);
///[LongPressHitTestResult] for hitting a phone number. ///[InAppWebViewHitTestResult] for hitting a phone number.
static const PHONE_TYPE = const LongPressHitTestResultType._internal(2); static const PHONE_TYPE = const InAppWebViewHitTestResultType._internal(2);
///[LongPressHitTestResult] for hitting a map address. ///[InAppWebViewHitTestResult] for hitting a map address.
static const GEO_TYPE = const LongPressHitTestResultType._internal(3); static const GEO_TYPE = const InAppWebViewHitTestResultType._internal(3);
///[LongPressHitTestResult] for hitting an email address. ///[InAppWebViewHitTestResult] for hitting an email address.
static const EMAIL_TYPE = const LongPressHitTestResultType._internal(4); static const EMAIL_TYPE = const InAppWebViewHitTestResultType._internal(4);
///[LongPressHitTestResult] for hitting an HTML::img tag. ///[InAppWebViewHitTestResult] for hitting an HTML::img tag.
static const IMAGE_TYPE = const LongPressHitTestResultType._internal(5); static const IMAGE_TYPE = const InAppWebViewHitTestResultType._internal(5);
///[LongPressHitTestResult] for hitting a HTML::a tag with src=http. ///[InAppWebViewHitTestResult] for hitting a HTML::a tag with src=http.
static const SRC_ANCHOR_TYPE = const LongPressHitTestResultType._internal(7); static const SRC_ANCHOR_TYPE = const InAppWebViewHitTestResultType._internal(7);
///[LongPressHitTestResult] for hitting a HTML::a tag with src=http + HTML::img. ///[InAppWebViewHitTestResult] for hitting a HTML::a tag with src=http + HTML::img.
static const SRC_IMAGE_ANCHOR_TYPE = const LongPressHitTestResultType._internal(8); static const SRC_IMAGE_ANCHOR_TYPE = const InAppWebViewHitTestResultType._internal(8);
///[LongPressHitTestResult] for hitting an edit text area. ///[InAppWebViewHitTestResult] for hitting an edit text area.
static const EDIT_TEXT_TYPE = const LongPressHitTestResultType._internal(9); static const EDIT_TEXT_TYPE = const InAppWebViewHitTestResultType._internal(9);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -2354,12 +2354,12 @@ class LongPressHitTestResultType { ...@@ -2354,12 +2354,12 @@ class LongPressHitTestResultType {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents the hit result for hitting an HTML elements. Used by [onLongPressHitTestResult] event. ///Class that represents the hit result for hitting an HTML elements.
class LongPressHitTestResult { class InAppWebViewHitTestResult {
///The type of the hit test result. ///The type of the hit test result.
LongPressHitTestResultType type; InAppWebViewHitTestResultType type;
///Additional type-dependant information about the result. ///Additional type-dependant information about the result.
String extra; String extra;
LongPressHitTestResult({this.type, this.extra}); InAppWebViewHitTestResult({this.type, this.extra});
} }
import 'package:flutter_inappwebview/src/context_menu.dart';
import 'types.dart'; import 'types.dart';
import 'in_app_webview_controller.dart'; import 'in_app_webview_controller.dart';
...@@ -233,7 +235,7 @@ abstract class WebView { ...@@ -233,7 +235,7 @@ abstract class WebView {
/// ///
///[hitTestResult] represents the hit result for hitting an HTML elements. ///[hitTestResult] represents the hit result for hitting an HTML elements.
final void Function(InAppWebViewController controller, final void Function(InAppWebViewController controller,
LongPressHitTestResult hitTestResult) onLongPressHitTestResult; InAppWebViewHitTestResult hitTestResult) onLongPressHitTestResult;
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing. ///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible. ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
...@@ -308,44 +310,49 @@ abstract class WebView { ...@@ -308,44 +310,49 @@ abstract class WebView {
///Initial options that will be used. ///Initial options that will be used.
final InAppWebViewGroupOptions initialOptions; final InAppWebViewGroupOptions initialOptions;
WebView( ///Context menu which contains custom menu items to be shown when [ContextMenu] is presented.
{this.onWebViewCreated, final ContextMenu contextMenu;
this.onLoadStart,
this.onLoadStop, WebView({
this.onLoadError, this.onWebViewCreated,
this.onLoadHttpError, this.onLoadStart,
this.onProgressChanged, this.onLoadStop,
this.onConsoleMessage, this.onLoadError,
this.shouldOverrideUrlLoading, this.onLoadHttpError,
this.onLoadResource, this.onProgressChanged,
this.onScrollChanged, this.onConsoleMessage,
this.onDownloadStart, this.shouldOverrideUrlLoading,
this.onLoadResourceCustomScheme, this.onLoadResource,
this.onCreateWindow, this.onScrollChanged,
this.onJsAlert, this.onDownloadStart,
this.onJsConfirm, this.onLoadResourceCustomScheme,
this.onJsPrompt, this.onCreateWindow,
this.onReceivedHttpAuthRequest, this.onJsAlert,
this.onReceivedServerTrustAuthRequest, this.onJsConfirm,
this.onReceivedClientCertRequest, this.onJsPrompt,
this.onFindResultReceived, this.onReceivedHttpAuthRequest,
this.shouldInterceptAjaxRequest, this.onReceivedServerTrustAuthRequest,
this.onAjaxReadyStateChange, this.onReceivedClientCertRequest,
this.onAjaxProgress, this.onFindResultReceived,
this.shouldInterceptFetchRequest, this.shouldInterceptAjaxRequest,
this.onUpdateVisitedHistory, this.onAjaxReadyStateChange,
this.onPrint, this.onAjaxProgress,
this.onLongPressHitTestResult, this.shouldInterceptFetchRequest,
this.androidOnSafeBrowsingHit, this.onUpdateVisitedHistory,
this.androidOnPermissionRequest, this.onPrint,
this.androidOnGeolocationPermissionsShowPrompt, this.onLongPressHitTestResult,
this.androidOnGeolocationPermissionsHidePrompt, this.androidOnSafeBrowsingHit,
this.iosOnWebContentProcessDidTerminate, this.androidOnPermissionRequest,
this.iosOnDidCommit, this.androidOnGeolocationPermissionsShowPrompt,
this.iosOnDidReceiveServerRedirectForProvisionalNavigation, this.androidOnGeolocationPermissionsHidePrompt,
this.initialUrl, this.iosOnWebContentProcessDidTerminate,
this.initialFile, this.iosOnDidCommit,
this.initialData, this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
this.initialHeaders, this.initialUrl,
this.initialOptions}); this.initialFile,
this.initialData,
this.initialHeaders,
this.initialOptions,
this.contextMenu
});
} }
\ No newline at end of file
...@@ -128,6 +128,9 @@ class InAppWebViewOptions ...@@ -128,6 +128,9 @@ class InAppWebViewOptions
///Set to `true` to disable horizontal scroll. The default value is `false`. ///Set to `true` to disable horizontal scroll. The default value is `false`.
bool disableHorizontalScroll; bool disableHorizontalScroll;
///Set to `true` to disable context menu. The default value is `false`.
bool disableContextMenu;
InAppWebViewOptions( InAppWebViewOptions(
{this.useShouldOverrideUrlLoading = false, {this.useShouldOverrideUrlLoading = false,
this.useOnLoadResource = false, this.useOnLoadResource = false,
...@@ -152,7 +155,8 @@ class InAppWebViewOptions ...@@ -152,7 +155,8 @@ class InAppWebViewOptions
this.cacheEnabled = true, this.cacheEnabled = true,
this.transparentBackground = false, this.transparentBackground = false,
this.disableVerticalScroll = false, this.disableVerticalScroll = false,
this.disableHorizontalScroll = false}) { this.disableHorizontalScroll = false,
this.disableContextMenu = false}) {
if (this.minimumFontSize == null) if (this.minimumFontSize == null)
this.minimumFontSize = Platform.isAndroid ? 8 : 0; this.minimumFontSize = Platform.isAndroid ? 8 : 0;
assert(!this.resourceCustomSchemes.contains("http") && assert(!this.resourceCustomSchemes.contains("http") &&
...@@ -189,7 +193,8 @@ class InAppWebViewOptions ...@@ -189,7 +193,8 @@ class InAppWebViewOptions
"cacheEnabled": cacheEnabled, "cacheEnabled": cacheEnabled,
"transparentBackground": transparentBackground, "transparentBackground": transparentBackground,
"disableVerticalScroll": disableVerticalScroll, "disableVerticalScroll": disableVerticalScroll,
"disableHorizontalScroll": disableHorizontalScroll "disableHorizontalScroll": disableHorizontalScroll,
"disableContextMenu": disableContextMenu
}; };
} }
...@@ -234,6 +239,7 @@ class InAppWebViewOptions ...@@ -234,6 +239,7 @@ class InAppWebViewOptions
options.transparentBackground = map["transparentBackground"]; options.transparentBackground = map["transparentBackground"];
options.disableVerticalScroll = map["disableVerticalScroll"]; options.disableVerticalScroll = map["disableVerticalScroll"];
options.disableHorizontalScroll = map["disableHorizontalScroll"]; options.disableHorizontalScroll = map["disableHorizontalScroll"];
options.disableContextMenu = map["disableContextMenu"];
return options; return options;
} }
} }
......
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.1.0 version: 3.2.0
homepage: https://github.com/pichillilorenzo/flutter_inappwebview homepage: https://github.com/pichillilorenzo/flutter_inappwebview
environment: environment:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment