Commit 2811fce4 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

updated webview options classes, fixed debuggingEnabled, added...

updated webview options classes, fixed debuggingEnabled, added getTRexRunnerHtml and getTRexRunnerCss methods
parent 299042f8
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
\ No newline at end of file
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false"> <configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false">
<option name="additionalArgs" value="--debug" />
<option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" /> <option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
......
This diff is collapsed.
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
- Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests - Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests
- Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods - Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods
- Added `getHtml` method - Added `getHtml` method
- Fun: added `getTRexRunnerHtml` and `getTRexRunnerCss` methods to get html (with javascript) and css to recreate the Chromium's t-rex runner game
### BREAKING CHANGES ### BREAKING CHANGES
- Deleted `WebResourceRequest` class - Deleted `WebResourceRequest` class
......
...@@ -118,7 +118,7 @@ public class ContentBlockerHandler { ...@@ -118,7 +118,7 @@ public class ContentBlockerHandler {
if (!trigger.ifTopUrl.isEmpty()) { if (!trigger.ifTopUrl.isEmpty()) {
boolean matchFound = false; boolean matchFound = false;
for (String topUrl : trigger.ifTopUrl) { for (String topUrl : trigger.ifTopUrl) {
if (webViewUrl[0].equals(topUrl)) { if (webViewUrl[0].startsWith(topUrl)) {
matchFound = true; matchFound = true;
break; break;
} }
...@@ -128,7 +128,7 @@ public class ContentBlockerHandler { ...@@ -128,7 +128,7 @@ public class ContentBlockerHandler {
} }
if (!trigger.unlessTopUrl.isEmpty()) { if (!trigger.unlessTopUrl.isEmpty()) {
for (String topUrl : trigger.unlessTopUrl) for (String topUrl : trigger.unlessTopUrl)
if (webViewUrl[0].equals(topUrl)) if (webViewUrl[0].startsWith(topUrl))
return null; return null;
} }
......
...@@ -387,6 +387,9 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -387,6 +387,9 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled) if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled); settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
if (newOptionsMap.get("debuggingEnabled") != null && options.debuggingEnabled != newOptions.debuggingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
setWebContentsDebuggingEnabled(newOptions.debuggingEnabled);
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically) if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically); settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
......
...@@ -639,18 +639,18 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -639,18 +639,18 @@ public class InAppWebViewClient extends WebViewClient {
Log.e(LOG_TAG, flutterResult.error); Log.e(LOG_TAG, flutterResult.error);
} }
else if (flutterResult.result != null) { else if (flutterResult.result != null) {
Map<String, String> res = (Map<String, String>) flutterResult.result; Map<String, Object> res = (Map<String, Object>) flutterResult.result;
WebResourceResponse response = null; WebResourceResponse response = null;
try { try {
response = webView.contentBlockerHandler.checkUrl(webView, url, res.get("content-type")); response = webView.contentBlockerHandler.checkUrl(webView, url, res.get("content-type").toString());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Log.e(LOG_TAG, e.getMessage()); Log.e(LOG_TAG, e.getMessage());
} }
if (response != null) if (response != null)
return response; return response;
byte[] data = Base64.decode(res.get("base64data"), Base64.DEFAULT); byte[] data = (byte[]) res.get("data");
return new WebResourceResponse(res.get("content-type"), res.get("content-encoding"), new ByteArrayInputStream(data)); return new WebResourceResponse(res.get("content-type").toString(), res.get("content-encoding").toString(), new ByteArrayInputStream(data));
} }
} }
......
...@@ -36,6 +36,11 @@ ...@@ -36,6 +36,11 @@
</p> </p>
</main> </main>
<!--<form method="POST" action="http://192.168.1.20:8082/test-post">
<input type="text" name="name" placeholder="name" value="Lorenzo">
<input type="submit" value="SEND">
</form>-->
<footer class="mastfoot mt-auto"> <footer class="mastfoot mt-auto">
<div class="inner"> <div class="inner">
<p>Cover template for <a target="_blank" href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p> <p>Cover template for <a target="_blank" href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
......
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
# platform :ios, '9.0' platform :ios, '8.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'
......
...@@ -267,7 +267,8 @@ ...@@ -267,7 +267,8 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/WKWebViewWithURLProtocol/WKWebViewWithURLProtocol.framework",
"${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework", "${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappbrowser/flutter_inappbrowser.framework", "${BUILT_PRODUCTS_DIR}/flutter_inappbrowser/flutter_inappbrowser.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
...@@ -275,6 +276,7 @@ ...@@ -275,6 +276,7 @@
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WKWebViewWithURLProtocol.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappbrowser.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappbrowser.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
...@@ -296,7 +298,7 @@ ...@@ -296,7 +298,7 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
......
...@@ -36,10 +36,12 @@ class _ChromeSafariExampleScreenState extends State<ChromeSafariExampleScreen> { ...@@ -36,10 +36,12 @@ class _ChromeSafariExampleScreenState extends State<ChromeSafariExampleScreen> {
return new Center( return new Center(
child: new RaisedButton( child: new RaisedButton(
onPressed: () async { onPressed: () async {
await widget.browser.open("https://flutter.dev/", options: [ await widget.browser.open("https://flutter.dev/",
AndroidChromeCustomTabsOptions(addShareButton: false), options: ChromeSafariBrowserClassOptions(
iOSSafariOptions(barCollapsingEnabled: true) androidChromeCustomTabsOptions: AndroidChromeCustomTabsOptions(addShareButton: false),
]); iosSafariOptions: IosSafariOptions(barCollapsingEnabled: true)
)
);
}, },
child: Text("Open Chrome Safari Browser")), child: Text("Open Chrome Safari Browser")),
); );
......
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -89,33 +90,34 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> { ...@@ -89,33 +90,34 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
//initialUrl: "https://192.168.1.20:4433/", //initialUrl: "https://192.168.1.20:4433/",
initialFile: "assets/index.html", initialFile: "assets/index.html",
initialHeaders: {}, initialHeaders: {},
initialOptions: [ initialOptions: InAppWebViewWidgetOptions(
InAppWebViewOptions( inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
//clearCache: true, //clearCache: true,
useShouldOverrideUrlLoading: true, useShouldOverrideUrlLoading: true,
useOnTargetBlank: true, useOnTargetBlank: true,
//useOnLoadResource: true, //useOnLoadResource: true,
useOnDownloadStart: true, useOnDownloadStart: true,
preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP, //preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP,
resourceCustomSchemes: ["my-special-custom-scheme"], resourceCustomSchemes: ["my-special-custom-scheme"],
/*contentBlockers: [ contentBlockers: [
ContentBlocker( ContentBlocker(
ContentBlockerTrigger(".*", ContentBlockerTrigger(".*",
resourceType: [ContentBlockerTriggerResourceType.IMAGE, ContentBlockerTriggerResourceType.STYLE_SHEET], resourceType: [ContentBlockerTriggerResourceType.IMAGE, ContentBlockerTriggerResourceType.STYLE_SHEET],
ifTopUrl: ["https://getbootstrap.com/"]), ifTopUrl: ["https://getbootstrap.com/"]),
ContentBlockerAction(ContentBlockerActionType.BLOCK) ContentBlockerAction(ContentBlockerActionType.BLOCK)
) )
]*/ ]
), ),
AndroidInAppWebViewOptions( androidInAppWebViewOptions: AndroidInAppWebViewOptions(
databaseEnabled: true, databaseEnabled: true,
appCacheEnabled: true, appCacheEnabled: true,
domStorageEnabled: true, domStorageEnabled: true,
geolocationEnabled: true, geolocationEnabled: true,
safeBrowsingEnabled: true, //safeBrowsingEnabled: true,
//blockNetworkImage: true, //blockNetworkImage: true,
), ),
], ),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {
webView = controller; webView = controller;
...@@ -148,6 +150,28 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> { ...@@ -148,6 +150,28 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
}, },
onLoadError: (InAppWebViewController controller, String url, int code, String message) async { onLoadError: (InAppWebViewController controller, String url, int code, String message) async {
print("error $url: $code, $message"); print("error $url: $code, $message");
var tRexHtml = await controller.getTRexRunnerHtml();
var tRexCss = await controller.getTRexRunnerCss();
controller.loadData("""
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no">
<style>${tRexCss}</style>
</head>
<body>
${tRexHtml}
<p>
URL ${url} failed to load.
</p>
<p>
Error: ${code}, ${message}
</p>
</body>
</html>
""");
}, },
onProgressChanged: onProgressChanged:
(InAppWebViewController controller, int progress) { (InAppWebViewController controller, int progress) {
...@@ -159,7 +183,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> { ...@@ -159,7 +183,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
print("override $url"); print("override $url");
controller.loadUrl(url); controller.loadUrl(url);
}, },
onLoadResource: (InAppWebViewController controller, WebResourceResponse response) { onLoadResource: (InAppWebViewController controller, LoadedResource response) {
print("Resource type: '"+response.initiatorType + "' started at: " + print("Resource type: '"+response.initiatorType + "' started at: " +
response.startTime.toString() + response.startTime.toString() +
"ms ---> duration: " + "ms ---> duration: " +
...@@ -187,8 +211,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> { ...@@ -187,8 +211,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async { onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async {
if (scheme == "my-special-custom-scheme") { if (scheme == "my-special-custom-scheme") {
var bytes = await rootBundle.load("assets/" + url.replaceFirst("my-special-custom-scheme://", "", 0)); var bytes = await rootBundle.load("assets/" + url.replaceFirst("my-special-custom-scheme://", "", 0));
var asBase64 = base64.encode(bytes.buffer.asUint8List()); var response = new CustomSchemeResponse(bytes.buffer.asUint8List(), "image/svg+xml", contentEnconding: "utf-8");
var response = new CustomSchemeResponse(asBase64, "image/svg+xml", contentEnconding: "utf-8");
return response; return response;
} }
return null; return null;
......
...@@ -400,7 +400,7 @@ class _MyAppState extends State<MyApp> { ...@@ -400,7 +400,7 @@ class _MyAppState extends State<MyApp> {
initialHeaders: { initialHeaders: {
}, },
initialOptions: [], initialOptions: InAppWebViewWidgetOptions(),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {
webView = controller; webView = controller;
}, },
......
...@@ -47,7 +47,7 @@ class MyInappBrowser extends InAppBrowser { ...@@ -47,7 +47,7 @@ class MyInappBrowser extends InAppBrowser {
} }
@override @override
void onLoadResource(WebResourceResponse response) { void onLoadResource(LoadedResource response) {
print("Started at: " + print("Started at: " +
response.startTime.toString() + response.startTime.toString() +
"ms ---> duration: " + "ms ---> duration: " +
...@@ -121,12 +121,14 @@ class _WebviewExampleScreenState extends State<WebviewExampleScreen> { ...@@ -121,12 +121,14 @@ class _WebviewExampleScreenState extends State<WebviewExampleScreen> {
widget.browser.openFile( widget.browser.openFile(
"assets/index.html", "assets/index.html",
//url: "https://www.google.com/", //url: "https://www.google.com/",
options: [ options: InAppBrowserClassOptions(
InAppWebViewOptions( inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
useShouldOverrideUrlLoading: true, useShouldOverrideUrlLoading: true,
useOnLoadResource: true, useOnLoadResource: true,
)
) )
] )
); );
}, },
child: Text("Open Webview Browser")), child: Text("Open Webview Browser")),
......
...@@ -20,13 +20,13 @@ class CustomeSchemeHandler : NSObject, WKURLSchemeHandler { ...@@ -20,13 +20,13 @@ class CustomeSchemeHandler : NSObject, WKURLSchemeHandler {
} }
else if (result as? NSObject) == FlutterMethodNotImplemented {} else if (result as? NSObject) == FlutterMethodNotImplemented {}
else { else {
let json: [String: String] let json: [String: Any]
if let r = result { if let r = result {
json = r as! [String: String] json = r as! [String: Any]
let urlResponse = URLResponse(url: url, mimeType: json["content-type"], expectedContentLength: -1, textEncodingName: json["content-encoding"]) let urlResponse = URLResponse(url: url, mimeType: json["content-type"] as! String, expectedContentLength: -1, textEncodingName: json["content-encoding"] as! String)
let data = Data(base64Encoded: json["base64data"]!, options: .ignoreUnknownCharacters) let data = json["data"] as! FlutterStandardTypedData
urlSchemeTask.didReceive(urlResponse) urlSchemeTask.didReceive(urlResponse)
urlSchemeTask.didReceive(data!) urlSchemeTask.didReceive(data.data)
urlSchemeTask.didFinish() urlSchemeTask.didFinish()
} }
} }
......
...@@ -14,9 +14,10 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView { ...@@ -14,9 +14,10 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
var webView: InAppWebView? var webView: InAppWebView?
var viewId: Int64 = 0 var viewId: Int64 = 0
var channel: FlutterMethodChannel? var channel: FlutterMethodChannel?
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: NSDictionary) { init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: NSDictionary) {
super.init() super.init()
self.registrar = registrar self.registrar = registrar
self.viewId = viewId self.viewId = viewId
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
import Flutter import Flutter
import Foundation import Foundation
import WebKit import WebKit
import WKWebViewWithURLProtocol
func currentTimeInMilliSeconds() -> Int64 { func currentTimeInMilliSeconds() -> Int64 {
let currentDate = Date() let currentDate = Date()
...@@ -242,6 +243,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -242,6 +243,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
static var credentialsProposed: [URLCredential] = [] static var credentialsProposed: [URLCredential] = []
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) { init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) {
super.init(frame: frame, configuration: configuration) super.init(frame: frame, configuration: configuration)
self.IABController = IABController self.IABController = IABController
self.IAWController = IAWController self.IAWController = IAWController
......
...@@ -47,6 +47,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin { ...@@ -47,6 +47,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
public init(with registrar: FlutterPluginRegistrar) { public init(with registrar: FlutterPluginRegistrar) {
super.init() super.init()
self.registrar = registrar self.registrar = registrar
self.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger()) self.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: channel!) registrar.addMethodCallDelegate(self, channel: channel!)
......
...@@ -17,7 +17,7 @@ A new Flutter plugin. ...@@ -17,7 +17,7 @@ A new Flutter plugin.
s.public_header_files = 'Classes/**/*.h' s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter' s.dependency 'Flutter'
s.platform = '8.0'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
s.swift_version = '5.0' s.swift_version = '5.0'
s.dependency "WKWebViewWithURLProtocol"
end end
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_inappbrowser/src/webview_options.dart';
import 'types.dart'; import 'types.dart';
import 'channel_manager.dart'; import 'channel_manager.dart';
...@@ -70,19 +70,29 @@ class ChromeSafariBrowser { ...@@ -70,19 +70,29 @@ class ChromeSafariBrowser {
///- __preferredControlTintColor__: Set the custom color of the control buttons on the navigation bar and the toolbar. ///- __preferredControlTintColor__: Set the custom color of the control buttons on the navigation bar and the toolbar.
///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles. ///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles.
///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles. ///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles.
Future<void> open(String url, {List<ChromeSafariBrowserOptions> options = const [], Map<String, String> headersFallback = const {}, List<BrowserOptions> optionsFallback = const []}) async { Future<void> open(String url, {ChromeSafariBrowserClassOptions options, Map<String, String> headersFallback = const {}, InAppBrowserClassOptions optionsFallback}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!'); this.throwIsAlreadyOpened(message: 'Cannot open $url!');
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) { if (Platform.isAndroid)
optionsMap.addAll(webViewOption.toMap()); optionsMap.addAll(options.androidChromeCustomTabsOptions?.toMap() ?? {});
}); else if (Platform.isIOS)
optionsMap.addAll(options.iosSafariOptions?.toMap() ?? {});
Map<String, dynamic> optionsFallbackMap = {}; Map<String, dynamic> optionsFallbackMap = {};
optionsFallback.forEach((webViewOption) { if (optionsFallback != null) {
optionsFallbackMap.addAll(webViewOption.toMap()); optionsFallbackMap.addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {});
}); optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsFallbackMap.addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsFallbackMap.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
}
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
......
...@@ -10,11 +10,26 @@ class ContentBlocker { ...@@ -10,11 +10,26 @@ class ContentBlocker {
"action": action.toMap() "action": action.toMap()
}; };
} }
static ContentBlocker fromMap(Map<dynamic, Map<dynamic, dynamic>> map) {
return ContentBlocker(
ContentBlockerTrigger.fromMap(
Map<String, dynamic>.from(map["trigger"])
),
ContentBlockerAction.fromMap(
Map<String, dynamic>.from(map["action"])
)
);
}
} }
class ContentBlockerTriggerResourceType { class ContentBlockerTriggerResourceType {
final String _value; final String _value;
const ContentBlockerTriggerResourceType._internal(this._value); const ContentBlockerTriggerResourceType._internal(this._value);
static ContentBlockerTriggerResourceType fromValue(String value) {
return (["document", "image", "LINK", "style-sheet", "script", "font",
"media", "svg-document", "raw"].contains(value)) ? ContentBlockerTriggerResourceType._internal(value) : null;
}
toValue() => _value; toValue() => _value;
static const DOCUMENT = const ContentBlockerTriggerResourceType._internal('document'); static const DOCUMENT = const ContentBlockerTriggerResourceType._internal('document');
...@@ -30,6 +45,9 @@ class ContentBlockerTriggerResourceType { ...@@ -30,6 +45,9 @@ class ContentBlockerTriggerResourceType {
class ContentBlockerTriggerLoadType { class ContentBlockerTriggerLoadType {
final String _value; final String _value;
const ContentBlockerTriggerLoadType._internal(this._value); const ContentBlockerTriggerLoadType._internal(this._value);
static ContentBlockerTriggerLoadType fromValue(String value) {
return (["first-party", "third-party"].contains(value)) ? ContentBlockerTriggerLoadType._internal(value) : null;
}
toValue() => _value; toValue() => _value;
static const FIRST_PARTY = const ContentBlockerTriggerLoadType._internal('first-party'); static const FIRST_PARTY = const ContentBlockerTriggerLoadType._internal('first-party');
...@@ -90,11 +108,40 @@ class ContentBlockerTrigger { ...@@ -90,11 +108,40 @@ class ContentBlockerTrigger {
return map; return map;
} }
static ContentBlockerTrigger fromMap(Map<String, dynamic> map) {
List<ContentBlockerTriggerResourceType> resourceType = [];
List<ContentBlockerTriggerLoadType> loadType = [];
List<String> resourceTypeStringList = List<String>.from(map["resource-type"] ?? []);
resourceTypeStringList.forEach((type) {
resourceType.add(ContentBlockerTriggerResourceType.fromValue(type));
});
List<String> loadTypeStringList = List<String>.from(map["load-type"] ?? []);
loadTypeStringList.forEach((type) {
loadType.add(ContentBlockerTriggerLoadType.fromValue(type));
});
return ContentBlockerTrigger(
map["url-filter"],
urlFilterIsCaseSensitive: map["url-filter-is-case-sensitive"],
ifDomain: List<String>.from(map["if-domain"] ?? []),
unlessDomain: List<String>.from(map["unless-domain"] ?? []),
resourceType: resourceType,
loadType: loadType,
ifTopUrl: List<String>.from(map["if-top-url"] ?? []),
unlessTopUrl: List<String>.from(map["unless-top-url"] ?? [])
);
}
} }
class ContentBlockerActionType { class ContentBlockerActionType {
final String _value; final String _value;
const ContentBlockerActionType._internal(this._value); const ContentBlockerActionType._internal(this._value);
static ContentBlockerActionType fromValue(String value) {
return (["block", "css-display-none", "make-https"].contains(value)) ? ContentBlockerActionType._internal(value) : null;
}
toValue() => _value; toValue() => _value;
static const BLOCK = const ContentBlockerActionType._internal('block'); static const BLOCK = const ContentBlockerActionType._internal('block');
...@@ -127,4 +174,11 @@ class ContentBlockerAction { ...@@ -127,4 +174,11 @@ class ContentBlockerAction {
return map; return map;
} }
static ContentBlockerAction fromMap(Map<String, dynamic> map) {
return ContentBlockerAction(
ContentBlockerActionType.fromValue(map["type"]),
selector: map["selector"]
);
}
} }
\ No newline at end of file
import 'dart:async'; import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_inappbrowser/src/webview_options.dart'; import 'package:flutter_inappbrowser/src/webview_options.dart';
...@@ -102,14 +103,22 @@ class InAppBrowser { ...@@ -102,14 +103,22 @@ class InAppBrowser {
/// - __allowsInlineMediaPlayback__: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. For this to work, add the `webkit-playsinline` attribute to any `<video>` elements. The default value is `false`. /// - __allowsInlineMediaPlayback__: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. For this to work, add the `webkit-playsinline` attribute to any `<video>` elements. The default value is `false`.
/// - __allowsPictureInPictureMediaPlayback__: Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`. /// - __allowsPictureInPictureMediaPlayback__: Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`.
/// - __spinner__: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`. /// - __spinner__: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
Future<void> open({String url = "about:blank", Map<String, String> headers = const {}, List<BrowserOptions> options = const []}) async { Future<void> open({String url = "about:blank", Map<String, String> headers = const {}, InAppBrowserClassOptions options}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!'); this.throwIsAlreadyOpened(message: 'Cannot open $url!');
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap()); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
}); optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
...@@ -140,7 +149,7 @@ class InAppBrowser { ...@@ -140,7 +149,7 @@ class InAppBrowser {
/// uses-material-design: true /// uses-material-design: true
/// ///
/// assets: /// assets:
/// - assets/index.html /// - assets/t-rex.html
/// - assets/css/ /// - assets/css/
/// - assets/images/ /// - assets/images/
/// ///
...@@ -149,17 +158,25 @@ class InAppBrowser { ...@@ -149,17 +158,25 @@ class InAppBrowser {
///Example of a `main.dart` file: ///Example of a `main.dart` file:
///```dart ///```dart
///... ///...
///inAppBrowser.openFile("assets/index.html"); ///inAppBrowser.openFile("assets/t-rex.html");
///... ///...
///``` ///```
Future<void> openFile(String assetFilePath, {Map<String, String> headers = const {}, List<BrowserOptions> options = const []}) async { Future<void> openFile(String assetFilePath, {Map<String, String> headers = const {}, InAppBrowserClassOptions options}) async {
assert(assetFilePath != null && assetFilePath.isNotEmpty); assert(assetFilePath != null && assetFilePath.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!'); this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap()); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
}); optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
...@@ -176,13 +193,21 @@ class InAppBrowser { ...@@ -176,13 +193,21 @@ class InAppBrowser {
///Opens a new [InAppBrowser] instance with [data] as a content, using [baseUrl] as the base URL for it. ///Opens a new [InAppBrowser] instance with [data] as a content, using [baseUrl] as the base URL for it.
///The [mimeType] parameter specifies the format of the data. ///The [mimeType] parameter specifies the format of the data.
///The [encoding] parameter specifies the encoding of the data. ///The [encoding] parameter specifies the encoding of the data.
Future<void> openData(String data, {String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", List<BrowserOptions> options = const []}) async { Future<void> openData(String data, {String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", InAppBrowserClassOptions options}) async {
assert(data != null); assert(data != null);
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap()); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
}); optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
...@@ -246,13 +271,21 @@ class InAppBrowser { ...@@ -246,13 +271,21 @@ class InAppBrowser {
} }
///Sets the [InAppBrowser] options with the new [options] and evaluates them. ///Sets the [InAppBrowser] options with the new [options] and evaluates them.
Future<void> setOptions(List<BrowserOptions> options) async { Future<void> setOptions(InAppBrowserClassOptions options) async {
this.throwIsNotOpened(); this.throwIsNotOpened();
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap()); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
}); optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
...@@ -262,15 +295,29 @@ class InAppBrowser { ...@@ -262,15 +295,29 @@ class InAppBrowser {
} }
///Gets the current [InAppBrowser] options as a `Map`. Returns `null` if the options are not setted yet. ///Gets the current [InAppBrowser] options as a `Map`. Returns `null` if the options are not setted yet.
Future<Map<String, dynamic>> getOptions() async { Future<InAppBrowserClassOptions> getOptions() async {
this.throwIsNotOpened(); this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions"); args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
InAppBrowserClassOptions inAppBrowserClassOptions = InAppBrowserClassOptions();
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args); Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args);
if (options != null) if (options != null) {
options = options.cast<String, dynamic>(); options = options.cast<String, dynamic>();
return options; inAppBrowserClassOptions.inAppBrowserOptions = InAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid) {
inAppBrowserClassOptions.androidInAppBrowserOptions = AndroidInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options);
}
else if (Platform.isIOS) {
inAppBrowserClassOptions.iosInAppBrowserOptions = IosInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
}
}
return inAppBrowserClassOptions;
} }
///Returns `true` if the [InAppBrowser] instance is opened, otherwise `false`. ///Returns `true` if the [InAppBrowser] instance is opened, otherwise `false`.
...@@ -323,7 +370,7 @@ class InAppBrowser { ...@@ -323,7 +370,7 @@ class InAppBrowser {
///Event fires when the [InAppBrowser] webview loads a resource. ///Event fires when the [InAppBrowser] webview loads a resource.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`.
void onLoadResource(WebResourceResponse response) { void onLoadResource(LoadedResource resource) {
} }
......
...@@ -45,7 +45,7 @@ class InAppLocalhostServer { ...@@ -45,7 +45,7 @@ class InAppLocalhostServer {
var body = List<int>(); var body = List<int>();
var path = request.requestedUri.path; var path = request.requestedUri.path;
path = (path.startsWith('/')) ? path.substring(1) : path; path = (path.startsWith('/')) ? path.substring(1) : path;
path += (path.endsWith('/')) ? 'index.html' : ''; path += (path.endsWith('/')) ? 't-rex.html' : '';
try { try {
body = (await rootBundle.load(path)) body = (await rootBundle.load(path))
......
...@@ -112,7 +112,7 @@ class InAppWebView extends StatefulWidget { ...@@ -112,7 +112,7 @@ class InAppWebView extends StatefulWidget {
///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`.
/// ///
///**NOTE only for Android**: to be able to listen this event, you need also the enable javascript. ///**NOTE only for Android**: to be able to listen this event, you need also the enable javascript.
final void Function(InAppWebViewController controller, WebResourceResponse response) onLoadResource; final void Function(InAppWebViewController controller, LoadedResource resource) onLoadResource;
///Event fires when the [InAppWebView] scrolls. ///Event fires when the [InAppWebView] scrolls.
/// ///
...@@ -207,7 +207,7 @@ class InAppWebView extends StatefulWidget { ...@@ -207,7 +207,7 @@ class InAppWebView extends StatefulWidget {
///Initial headers that will be used. ///Initial headers that will be used.
final Map<String, String> initialHeaders; final Map<String, String> initialHeaders;
///Initial options that will be used. ///Initial options that will be used.
final List<WebViewOptions> initialOptions; final InAppWebViewWidgetOptions initialOptions;
/// `gestureRecognizers` specifies which gestures should be consumed by the web view. /// `gestureRecognizers` specifies which gestures should be consumed by the web view.
/// It is possible for other gesture recognizers to be competing with the web view on pointer /// It is possible for other gesture recognizers to be competing with the web view on pointer
/// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle /// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle
...@@ -223,7 +223,7 @@ class InAppWebView extends StatefulWidget { ...@@ -223,7 +223,7 @@ class InAppWebView extends StatefulWidget {
this.initialFile, this.initialFile,
this.initialData, this.initialData,
this.initialHeaders = const {}, this.initialHeaders = const {},
this.initialOptions = const [], this.initialOptions,
this.onWebViewCreated, this.onWebViewCreated,
this.onLoadStart, this.onLoadStart,
this.onLoadStop, this.onLoadStop,
...@@ -259,10 +259,11 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -259,10 +259,11 @@ class _InAppWebViewState extends State<InAppWebView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Map<String, dynamic> initialOptions = {}; Map<String, dynamic> initialOptions = {};
widget.initialOptions.forEach((webViewOption) { initialOptions.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {});
if ((Platform.isAndroid && webViewOption is AndroidOptions) || (Platform.isIOS && webViewOption is iOSOptions)) if (Platform.isAndroid)
initialOptions.addAll(webViewOption.toMap()); initialOptions.addAll(widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {});
}); else if (Platform.isIOS)
initialOptions.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {});
if (defaultTargetPlatform == TargetPlatform.android) { if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView( return AndroidView(
...@@ -404,7 +405,7 @@ class InAppWebViewController { ...@@ -404,7 +405,7 @@ class InAppWebViewController {
double startTime = call.arguments["startTime"]; double startTime = call.arguments["startTime"];
double duration = call.arguments["duration"]; double duration = call.arguments["duration"];
var response = new WebResourceResponse(initiatorType, url, startTime, duration); var response = new LoadedResource(initiatorType, url, startTime, duration);
if (_widget != null && _widget.onLoadResource != null) if (_widget != null && _widget.onLoadResource != null)
_widget.onLoadResource(this, response); _widget.onLoadResource(this, response);
...@@ -606,8 +607,8 @@ class InAppWebViewController { ...@@ -606,8 +607,8 @@ class InAppWebViewController {
///- downloading it using an `HttpClient` through the WebView's current url. ///- downloading it using an `HttpClient` through the WebView's current url.
Future<String> getHtml() async { Future<String> getHtml() async {
var html = ""; var html = "";
Map<String, dynamic> options = await getOptions(); InAppWebViewWidgetOptions options = await getOptions();
if (options != null && options["javaScriptEnabled"] == true) { if (options != null && options.inAppWebViewOptions.javaScriptEnabled == true) {
html = await injectScriptCode("window.document.getElementsByTagName('html')[0].outerHTML;"); html = await injectScriptCode("window.document.getElementsByTagName('html')[0].outerHTML;");
if (html.isNotEmpty) if (html.isNotEmpty)
return html; return html;
...@@ -803,7 +804,7 @@ class InAppWebViewController { ...@@ -803,7 +804,7 @@ class InAppWebViewController {
/// uses-material-design: true /// uses-material-design: true
/// ///
/// assets: /// assets:
/// - assets/index.html /// - assets/t-rex.html
/// - assets/css/ /// - assets/css/
/// - assets/images/ /// - assets/images/
/// ///
...@@ -812,7 +813,7 @@ class InAppWebViewController { ...@@ -812,7 +813,7 @@ class InAppWebViewController {
///Example of a `main.dart` file: ///Example of a `main.dart` file:
///```dart ///```dart
///... ///...
///inAppBrowser.loadFile("assets/index.html"); ///inAppBrowser.loadFile("assets/t-rex.html");
///... ///...
///``` ///```
Future<void> loadFile(String assetFilePath, {Map<String, String> headers = const {}}) async { Future<void> loadFile(String assetFilePath, {Map<String, String> headers = const {}}) async {
...@@ -1042,27 +1043,44 @@ class InAppWebViewController { ...@@ -1042,27 +1043,44 @@ class InAppWebViewController {
} }
///Sets the [InAppWebView] options with the new [options] and evaluates them. ///Sets the [InAppWebView] options with the new [options] and evaluates them.
Future<void> setOptions(Map<String, dynamic> options) async { Future<void> setOptions(InAppWebViewWidgetOptions options) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) { if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened(); _inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid); args.putIfAbsent('uuid', () => _inAppBrowserUuid);
} }
args.putIfAbsent('options', () => options);
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid)
optionsMap.addAll(options.androidInAppWebViewOptions?.toMap() ?? {});
else if (Platform.isIOS)
optionsMap.addAll(options.iosInAppWebViewOptions?.toMap() ?? {});
args.putIfAbsent('options', () => optionsMap);
await _channel.invokeMethod('setOptions', args); await _channel.invokeMethod('setOptions', args);
} }
///Gets the current [InAppWebView] options. Returns `null` if the options are not setted yet. ///Gets the current [InAppWebView] options. Returns the options with `null` value if they are not set yet.
Future<Map<String, dynamic>> getOptions() async { Future<InAppWebViewWidgetOptions> getOptions() async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) { if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened(); _inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid); args.putIfAbsent('uuid', () => _inAppBrowserUuid);
} }
InAppWebViewWidgetOptions inAppWebViewWidgetOptions = InAppWebViewWidgetOptions();
Map<dynamic, dynamic> options = await _channel.invokeMethod('getOptions', args); Map<dynamic, dynamic> options = await _channel.invokeMethod('getOptions', args);
if (options != null) if (options != null) {
options = options.cast<String, dynamic>(); options = options.cast<String, dynamic>();
return options; inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid)
inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options);
else if (Platform.isIOS)
inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
}
return inAppWebViewWidgetOptions;
} }
///Gets the WebHistory for this WebView. This contains the back/forward list for use in querying each item in the history stack. ///Gets the WebHistory for this WebView. This contains the back/forward list for use in querying each item in the history stack.
...@@ -1230,4 +1248,14 @@ class InAppWebViewController { ...@@ -1230,4 +1248,14 @@ class InAppWebViewController {
} }
await _channel.invokeMethod('clearMatches', args); await _channel.invokeMethod('clearMatches', args);
} }
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss()].
Future<String> getTRexRunnerHtml() async {
return await rootBundle.loadString("packages/flutter_inappbrowser/t_rex_runner/t-rex.html");
}
///Gets the css of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerHtml()].
Future<String> getTRexRunnerCss() async {
return await rootBundle.loadString("packages/flutter_inappbrowser/t_rex_runner/t-rex.css");
}
} }
This diff is collapsed.
This diff is collapsed.
#main-frame-error {
box-sizing: border-box;
padding: 0 10%;
font-size: 1em;
line-height: 1.55;
margin: 0 auto;
max-width: 600px;
padding-top: 100px;
width: 100%;
}
#main-content {
font-size: 1em;
line-height: 1.55;
margin: 0 auto;
max-width: 600px;
padding-top: 100px;
width: 100%;
}
#t-rex-icon {
font-size: 1em;
line-height: 1.55;
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
margin: 0 0 40px;
width: 72px;
display: inline-block;
content: -webkit-image-set(
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAGxJREFUeF7tyMEJwkAQRuFf5ipMKxYQiJ3Z2nSwrWwBA0+DQZcdxEOueaePp9+dQZFB7GpUcURSVU66yVNFj6LFICatThZB6r/ko/pbRpUgilY0Cbw5sNmb9txGXUKyuH7eV25x39DtJXUNPQGJtWFV+BT/QAAAAABJRU5ErkJggg==)
1x,
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQBAMAAAAVaP+LAAAAGFBMVEUAAABTU1NNTU1TU1NPT09SUlJSUlJTU1O8B7DEAAAAB3RSTlMAoArVKvVgBuEdKgAAAJ1JREFUeF7t1TEOwyAMQNG0Q6/UE+RMXD9d/tC6womIFSL9P+MnAYOXeTIzMzMzMzMzaz8J9Ri6HoITmuHXhISE8nEh9yxDh55aCEUoTGbbQwjqHwIkRAEiIaG0+0AA9VBMaE89Rogeoww936MQrWdBr4GN/z0IAdQ6nQ/FIpRXDwHcA+JIJcQowQAlFUA0MfQpXLlVQfkzR4igS6ENjknm/wiaGhsAAAAASUVORK5CYII=)
2x
);
position: relative;
visibility: hidden;
}
#offline-resources {
display: none;
}
#main-frame-error > .runner-container {
height: 150px;
max-width: 600px;
overflow: hidden;
position: absolute;
top: 35px;
width: 44px;
}
#main-frame-error > .controller {
background: rgba(247, 247, 247, 0.1);
height: 100vh;
left: 0;
position: absolute;
top: 0;
width: 100vw;
z-index: 9;
}
#main-frame-error .hidden {
display: none;
}
This diff is collapsed.
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
const express = require('express') const express = require('express')
var https = require('https') var https = require('https')
const auth = require('basic-auth') const auth = require('basic-auth')
const app = express()
const appHttps = express() const appHttps = express()
const appAuthBasic = express() const appAuthBasic = express()
const fs = require('fs') const fs = require('fs')
...@@ -78,6 +79,40 @@ appAuthBasic.get("/", (req, res) => { ...@@ -78,6 +79,40 @@ appAuthBasic.get("/", (req, res) => {
</body> </body>
</html> </html>
`); `);
res.end()
}) })
appAuthBasic.listen(8081) appAuthBasic.listen(8081)
\ No newline at end of file
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.get("/", (req, res) => {
res.send(`
<html>
<head>
</head>
<body>
<p>HELLO</p>
</body>
</html>
`);
res.end()
})
app.post("/test-post", (req, res) => {
res.send(`
<html>
<head>
</head>
<body>
<p>HELLO ${req.body.name}!</p>
</body>
</html>
`);
res.end()
})
app.listen(8082)
\ No newline at end of file
...@@ -24,6 +24,9 @@ flutter: ...@@ -24,6 +24,9 @@ flutter:
androidPackage: com.pichillilorenzo.flutter_inappbrowser androidPackage: com.pichillilorenzo.flutter_inappbrowser
pluginClass: InAppBrowserFlutterPlugin pluginClass: InAppBrowserFlutterPlugin
assets:
- packages/flutter_inappbrowser/t_rex_runner/t-rex.html
- packages/flutter_inappbrowser/t_rex_runner/t-rex.css
# To add assets to your plugin package, add an assets section, like this: # To add assets to your plugin package, add an assets section, like this:
# assets: # assets:
# - images/a_dot_burr.jpeg # - images/a_dot_burr.jpeg
......
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