Throw an error if any controller is used after being disposed, created internal ChannelController class
This commit is contained in:
parent
612ed1eec3
commit
a623ee718d
|
@ -1,6 +1,7 @@
|
|||
## 6.0.0-beta.26
|
||||
|
||||
- Updated return value for `CookieManager.setCookie` method to be `Future<bool>`. The return value indicates whether the cookie was set successfully.
|
||||
- Throw an error if any controller is used after being disposed
|
||||
- Updated return value for `CookieManager.setCookie` method to be `Future<bool>`. The return value indicates whether the cookie was set successfully
|
||||
- Merged "feat(ios): optional tradeoff to fix ios input delay" [#1665](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1665) (thanks to [andreasgangso](https://github.com/andreasgangso))
|
||||
- Merged "Fix ios multiple flutter presenting error" [#1736](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1736) (thanks to [AlexT84](https://github.com/AlexT84))
|
||||
- Merged "fix cert parsing for ios 12" [#1822](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1822) (thanks to [darkang3lz92](https://github.com/darkang3lz92))
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_i
|
|||
import '../types/proxy_rule.dart';
|
||||
import 'webview_feature.dart';
|
||||
import '../in_app_webview/webview.dart';
|
||||
import '../types/main.dart';
|
||||
|
||||
part 'proxy_controller.g.dart';
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:typed_data';
|
|||
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
|
||||
|
||||
import 'chrome_safari_browser.dart';
|
||||
import 'chrome_safari_browser_menu_item.dart';
|
||||
import '../web_uri.dart';
|
||||
|
||||
part 'chrome_safari_action_button.g.dart';
|
||||
|
|
|
@ -26,7 +26,7 @@ import 'chrome_safari_browser_secondary_toolbar.dart';
|
|||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
class ChromeSafariBrowser {
|
||||
class ChromeSafariBrowser extends ChannelController {
|
||||
///Debug settings.
|
||||
static DebugLoggingSettings debugLoggingSettings = DebugLoggingSettings();
|
||||
|
||||
|
@ -37,36 +37,23 @@ class ChromeSafariBrowser {
|
|||
Map<int, ChromeSafariBrowserMenuItem> _menuItems = new HashMap();
|
||||
ChromeSafariBrowserSecondaryToolbar? _secondaryToolbar;
|
||||
bool _isOpened = false;
|
||||
MethodChannel? _channel;
|
||||
static const MethodChannel _sharedChannel =
|
||||
const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser');
|
||||
|
||||
ChromeSafariBrowser() {
|
||||
id = IdGenerator.generate();
|
||||
this._channel =
|
||||
channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
_isOpened = false;
|
||||
}
|
||||
|
||||
_init() {
|
||||
this._channel =
|
||||
channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
_debugLog(String method, dynamic args) {
|
||||
|
@ -116,7 +103,7 @@ class ChromeSafariBrowser {
|
|||
break;
|
||||
case "onClosed":
|
||||
_isOpened = false;
|
||||
_dispose();
|
||||
dispose();
|
||||
onClosed();
|
||||
break;
|
||||
case "onItemActionPerform":
|
||||
|
@ -196,8 +183,8 @@ class ChromeSafariBrowser {
|
|||
List<WebUri>? otherLikelyURLs,
|
||||
WebUri? referrer,
|
||||
@Deprecated('Use settings instead')
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
ChromeSafariBrowserClassOptions? options,
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
ChromeSafariBrowserClassOptions? options,
|
||||
ChromeSafariBrowserSettings? settings}) async {
|
||||
assert(!_isOpened, 'The browser is already opened.');
|
||||
_isOpened = true;
|
||||
|
@ -262,7 +249,7 @@ class ChromeSafariBrowser {
|
|||
args.putIfAbsent('otherLikelyURLs',
|
||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||
args.putIfAbsent('referrer', () => referrer?.toString());
|
||||
await _channel?.invokeMethod("launchUrl", args);
|
||||
await channel?.invokeMethod("launchUrl", args);
|
||||
}
|
||||
|
||||
///Tells the browser of a likely future navigation to a URL.
|
||||
|
@ -283,7 +270,7 @@ class ChromeSafariBrowser {
|
|||
args.putIfAbsent('url', () => url?.toString());
|
||||
args.putIfAbsent('otherLikelyURLs',
|
||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||
return await _channel?.invokeMethod("mayLaunchUrl", args);
|
||||
return await channel?.invokeMethod<bool>("mayLaunchUrl", args) ?? false;
|
||||
}
|
||||
|
||||
///Requests to validate a relationship between the application and an origin.
|
||||
|
@ -308,7 +295,7 @@ class ChromeSafariBrowser {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('relation', () => relation.toNativeValue());
|
||||
args.putIfAbsent('origin', () => origin.toString());
|
||||
return await _channel?.invokeMethod("validateRelationship", args);
|
||||
return await channel?.invokeMethod<bool>("validateRelationship", args) ?? false;
|
||||
}
|
||||
|
||||
///Closes the [ChromeSafariBrowser] instance.
|
||||
|
@ -318,7 +305,7 @@ class ChromeSafariBrowser {
|
|||
///- iOS
|
||||
Future<void> close() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod("close", args);
|
||||
await channel?.invokeMethod("close", args);
|
||||
}
|
||||
|
||||
///Set a custom action button.
|
||||
|
@ -342,7 +329,7 @@ class ChromeSafariBrowser {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('icon', () => icon);
|
||||
args.putIfAbsent('description', () => description);
|
||||
await _channel?.invokeMethod("updateActionButton", args);
|
||||
await channel?.invokeMethod("updateActionButton", args);
|
||||
_actionButton?.icon = icon;
|
||||
_actionButton?.description = description;
|
||||
}
|
||||
|
@ -368,7 +355,7 @@ class ChromeSafariBrowser {
|
|||
ChromeSafariBrowserSecondaryToolbar secondaryToolbar) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('secondaryToolbar', () => secondaryToolbar.toMap());
|
||||
await _channel?.invokeMethod("updateSecondaryToolbar", args);
|
||||
await channel?.invokeMethod("updateSecondaryToolbar", args);
|
||||
this._secondaryToolbar = secondaryToolbar;
|
||||
}
|
||||
|
||||
|
@ -414,7 +401,7 @@ class ChromeSafariBrowser {
|
|||
///- Android
|
||||
static Future<int> getMaxToolbarItems() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _sharedChannel.invokeMethod("getMaxToolbarItems", args);
|
||||
return await _sharedChannel.invokeMethod<int>("getMaxToolbarItems", args) ?? 0;
|
||||
}
|
||||
|
||||
///Clear associated website data accrued from browsing activity within your app.
|
||||
|
@ -543,8 +530,9 @@ class ChromeSafariBrowser {
|
|||
}
|
||||
|
||||
///Disposes the channel.
|
||||
void _dispose() {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
@override
|
||||
@mustCallSuper
|
||||
void dispose() {
|
||||
disposeChannel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,7 @@ import '../util.dart';
|
|||
///- Android native WebView
|
||||
///- iOS
|
||||
///- MacOS
|
||||
class FindInteractionController {
|
||||
MethodChannel? _channel;
|
||||
|
||||
class FindInteractionController extends ChannelController {
|
||||
///Debug settings.
|
||||
static DebugLoggingSettings debugLoggingSettings = DebugLoggingSettings();
|
||||
|
||||
|
@ -81,7 +79,7 @@ class FindInteractionController {
|
|||
Future<void> findAll({String? find}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('find', () => find);
|
||||
await _channel?.invokeMethod('findAll', args);
|
||||
await channel?.invokeMethod('findAll', args);
|
||||
}
|
||||
|
||||
///Highlights and scrolls to the next match found by [findAll]. Notifies [FindInteractionController.onFindResultReceived] listener.
|
||||
|
@ -99,7 +97,7 @@ class FindInteractionController {
|
|||
Future<void> findNext({bool forward = true}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('forward', () => forward);
|
||||
await _channel?.invokeMethod('findNext', args);
|
||||
await channel?.invokeMethod('findNext', args);
|
||||
}
|
||||
|
||||
///Clears the highlighting surrounding text matches created by [findAll].
|
||||
|
@ -114,7 +112,7 @@ class FindInteractionController {
|
|||
///- MacOS
|
||||
Future<void> clearMatches() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('clearMatches', args);
|
||||
await channel?.invokeMethod('clearMatches', args);
|
||||
}
|
||||
|
||||
///Pre-populate the search text to be used.
|
||||
|
@ -129,7 +127,7 @@ class FindInteractionController {
|
|||
Future<void> setSearchText(String? searchText) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('searchText', () => searchText);
|
||||
await _channel?.invokeMethod('setSearchText', args);
|
||||
await channel?.invokeMethod('setSearchText', args);
|
||||
}
|
||||
|
||||
///Get the search text used.
|
||||
|
@ -143,7 +141,7 @@ class FindInteractionController {
|
|||
///- MacOS
|
||||
Future<String?> getSearchText() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getSearchText', args);
|
||||
return await channel?.invokeMethod<String?>('getSearchText', args);
|
||||
}
|
||||
|
||||
///A Boolean value that indicates when the find panel displays onscreen.
|
||||
|
@ -154,7 +152,7 @@ class FindInteractionController {
|
|||
///- iOS ([Official API - UIFindInteraction.isFindNavigatorVisible](https://developer.apple.com/documentation/uikit/uifindinteraction/3975828-isfindnavigatorvisible?changes=_2))
|
||||
Future<bool?> isFindNavigatorVisible() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isFindNavigatorVisible', args);
|
||||
return await channel?.invokeMethod<bool?>('isFindNavigatorVisible', args);
|
||||
}
|
||||
|
||||
///Updates the results the interface displays for the active search.
|
||||
|
@ -165,7 +163,7 @@ class FindInteractionController {
|
|||
///- iOS ([Official API - UIFindInteraction.updateResultCount](https://developer.apple.com/documentation/uikit/uifindinteraction/3975835-updateresultcount?changes=_2))
|
||||
Future<void> updateResultCount() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('updateResultCount', args);
|
||||
await channel?.invokeMethod('updateResultCount', args);
|
||||
}
|
||||
|
||||
///Begins a search, displaying the find panel.
|
||||
|
@ -176,7 +174,7 @@ class FindInteractionController {
|
|||
///- iOS ([Official API - UIFindInteraction.presentFindNavigator](https://developer.apple.com/documentation/uikit/uifindinteraction/3975832-presentfindnavigator?changes=_2))
|
||||
Future<void> presentFindNavigator() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('presentFindNavigator', args);
|
||||
await channel?.invokeMethod('presentFindNavigator', args);
|
||||
}
|
||||
|
||||
///Dismisses the find panel, if present.
|
||||
|
@ -187,7 +185,7 @@ class FindInteractionController {
|
|||
///- iOS ([Official API - UIFindInteraction.dismissFindNavigator](https://developer.apple.com/documentation/uikit/uifindinteraction/3975827-dismissfindnavigator?changes=_2))
|
||||
Future<void> dismissFindNavigator() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('dismissFindNavigator', args);
|
||||
await channel?.invokeMethod('dismissFindNavigator', args);
|
||||
}
|
||||
|
||||
///If there's a currently active find session, returns the active find session.
|
||||
|
@ -199,33 +197,23 @@ class FindInteractionController {
|
|||
Future<FindSession?> getActiveFindSession() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? result =
|
||||
(await _channel?.invokeMethod('getActiveFindSession', args))
|
||||
(await channel?.invokeMethod('getActiveFindSession', args))
|
||||
?.cast<String, dynamic>();
|
||||
return FindSession.fromMap(result);
|
||||
}
|
||||
|
||||
///Disposes the controller.
|
||||
@override
|
||||
void dispose({bool isKeepAlive = false}) {
|
||||
if (!isKeepAlive) {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
}
|
||||
_channel = null;
|
||||
disposeChannel(removeMethodCallHandler: !isKeepAlive);
|
||||
}
|
||||
}
|
||||
|
||||
extension InternalFindInteractionController on FindInteractionController {
|
||||
void init(dynamic id) {
|
||||
this._channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_find_interaction_$id');
|
||||
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
if (_channel == null) return null;
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:collection';
|
|||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../context_menu/context_menu.dart';
|
||||
|
@ -28,7 +29,7 @@ import '../pull_to_refresh/pull_to_refresh_controller.dart';
|
|||
///- Android native WebView
|
||||
///- iOS
|
||||
///- MacOS
|
||||
class InAppBrowser {
|
||||
class InAppBrowser extends ChannelController {
|
||||
///Debug settings.
|
||||
static DebugLoggingSettings debugLoggingSettings = DebugLoggingSettings();
|
||||
|
||||
|
@ -48,7 +49,6 @@ class InAppBrowser {
|
|||
final UnmodifiableListView<UserScript>? initialUserScripts;
|
||||
|
||||
bool _isOpened = false;
|
||||
MethodChannel? _channel;
|
||||
static const MethodChannel _sharedChannel =
|
||||
const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
||||
|
||||
|
@ -70,18 +70,13 @@ class InAppBrowser {
|
|||
}
|
||||
|
||||
_init() {
|
||||
this._channel =
|
||||
channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
|
||||
_webViewController = new InAppWebViewController.fromInAppBrowser(
|
||||
this._channel!, this, this.initialUserScripts);
|
||||
channel!, this, this.initialUserScripts);
|
||||
pullToRefreshController?.init(id);
|
||||
findInteractionController?.init(id);
|
||||
}
|
||||
|
@ -113,7 +108,7 @@ class InAppBrowser {
|
|||
case "onExit":
|
||||
_debugLog(call.method, call.arguments);
|
||||
_isOpened = false;
|
||||
_dispose();
|
||||
dispose();
|
||||
onExit();
|
||||
break;
|
||||
default:
|
||||
|
@ -366,7 +361,7 @@ class InAppBrowser {
|
|||
assert(_isOpened, 'The browser is not opened.');
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('show', args);
|
||||
await channel?.invokeMethod('show', args);
|
||||
}
|
||||
|
||||
///Hides the [InAppBrowser] window. Calling this has no effect if the [InAppBrowser] was already hidden.
|
||||
|
@ -379,7 +374,7 @@ class InAppBrowser {
|
|||
assert(_isOpened, 'The browser is not opened.');
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('hide', args);
|
||||
await channel?.invokeMethod('hide', args);
|
||||
}
|
||||
|
||||
///Closes the [InAppBrowser] window.
|
||||
|
@ -392,7 +387,7 @@ class InAppBrowser {
|
|||
assert(_isOpened, 'The browser is not opened.');
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('close', args);
|
||||
await channel?.invokeMethod('close', args);
|
||||
}
|
||||
|
||||
///Check if the Web View of the [InAppBrowser] instance is hidden.
|
||||
|
@ -405,7 +400,7 @@ class InAppBrowser {
|
|||
assert(_isOpened, 'The browser is not opened.');
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isHidden', args);
|
||||
return await channel?.invokeMethod<bool>('isHidden', args) ?? false;
|
||||
}
|
||||
|
||||
///Use [setSettings] instead.
|
||||
|
@ -415,7 +410,7 @@ class InAppBrowser {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('settings', () => options.toMap());
|
||||
await _channel?.invokeMethod('setSettings', args);
|
||||
await channel?.invokeMethod('setSettings', args);
|
||||
}
|
||||
|
||||
///Use [getSettings] instead.
|
||||
|
@ -425,7 +420,7 @@ class InAppBrowser {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
Map<dynamic, dynamic>? options =
|
||||
await _channel?.invokeMethod('getSettings', args);
|
||||
await channel?.invokeMethod('getSettings', args);
|
||||
if (options != null) {
|
||||
options = options.cast<String, dynamic>();
|
||||
return InAppBrowserClassOptions.fromMap(options as Map<String, dynamic>);
|
||||
|
@ -446,7 +441,7 @@ class InAppBrowser {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('settings', () => settings.toMap());
|
||||
await _channel?.invokeMethod('setSettings', args);
|
||||
await channel?.invokeMethod('setSettings', args);
|
||||
}
|
||||
|
||||
///Gets the current [InAppBrowser] settings. Returns `null` if it wasn't able to get them.
|
||||
|
@ -461,7 +456,7 @@ class InAppBrowser {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
Map<dynamic, dynamic>? settings =
|
||||
await _channel?.invokeMethod('getSettings', args);
|
||||
await channel?.invokeMethod('getSettings', args);
|
||||
if (settings != null) {
|
||||
settings = settings.cast<String, dynamic>();
|
||||
return InAppBrowserClassSettings.fromMap(
|
||||
|
@ -1361,9 +1356,10 @@ class InAppBrowser {
|
|||
void onContentSizeChanged(Size oldContentSize, Size newContentSize) {}
|
||||
|
||||
///Disposes the channel and controllers.
|
||||
void _dispose() {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
@override
|
||||
@mustCallSuper
|
||||
void dispose() {
|
||||
disposeChannel();
|
||||
_webViewController?.dispose();
|
||||
_webViewController = null;
|
||||
pullToRefreshController?.dispose();
|
||||
|
|
|
@ -29,7 +29,7 @@ import '../types/disposable.dart';
|
|||
///- Web
|
||||
///- MacOS
|
||||
///{@endtemplate}
|
||||
class HeadlessInAppWebView implements WebView, Disposable {
|
||||
class HeadlessInAppWebView extends ChannelController implements WebView, Disposable {
|
||||
///View ID.
|
||||
late final String id;
|
||||
|
||||
|
@ -38,7 +38,6 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
|||
|
||||
static const MethodChannel _sharedChannel =
|
||||
const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview');
|
||||
MethodChannel? _channel;
|
||||
|
||||
InAppWebViewController? _webViewController;
|
||||
|
||||
|
@ -187,19 +186,13 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
|||
_webViewController = InAppWebViewController(id, this);
|
||||
pullToRefreshController?.init(id);
|
||||
findInteractionController?.init(id);
|
||||
this._channel =
|
||||
channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case "onWebViewCreated":
|
||||
if (onWebViewCreated != null && _webViewController != null) {
|
||||
|
@ -310,9 +303,8 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
|||
return;
|
||||
}
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('dispose', args);
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
await channel?.invokeMethod('dispose', args);
|
||||
disposeChannel();
|
||||
_started = false;
|
||||
_running = false;
|
||||
_webViewController?.dispose();
|
||||
|
@ -353,7 +345,7 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('size', () => size.toMap());
|
||||
await _channel?.invokeMethod('setSize', args);
|
||||
await channel?.invokeMethod('setSize', args);
|
||||
}
|
||||
|
||||
///Gets the current size in pixels of the WebView.
|
||||
|
@ -372,7 +364,7 @@ class HeadlessInAppWebView implements WebView, Disposable {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic> sizeMap =
|
||||
(await _channel?.invokeMethod('getSize', args))
|
||||
(await channel?.invokeMethod('getSize', args))
|
||||
?.cast<String, dynamic>();
|
||||
return MapSize.fromMap(sizeMap);
|
||||
}
|
||||
|
|
|
@ -50,12 +50,11 @@ final _JAVASCRIPT_HANDLER_FORBIDDEN_NAMES = UnmodifiableListView<String>([
|
|||
///
|
||||
///If you are using the [InAppWebView] widget, an [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated]
|
||||
///callback. Instead, if you are using an [InAppBrowser] instance, you can get it through the [InAppBrowser.webViewController] attribute.
|
||||
class InAppWebViewController {
|
||||
class InAppWebViewController extends ChannelController {
|
||||
WebView? _webview;
|
||||
MethodChannel? _channel;
|
||||
static final MethodChannel _staticChannel = IN_APP_WEBVIEW_STATIC_CHANNEL;
|
||||
|
||||
// properties to be saved and restored for keep alive feature
|
||||
// List of properties to be saved and restored for keep alive feature
|
||||
Map<String, JavaScriptHandlerCallback> _javaScriptHandlersMap =
|
||||
HashMap<String, JavaScriptHandlerCallback>();
|
||||
Map<UserScriptInjectionTime, List<UserScript>> _userScripts = {
|
||||
|
@ -64,6 +63,8 @@ class InAppWebViewController {
|
|||
};
|
||||
Set<String> _webMessageListenerObjNames = Set();
|
||||
Map<String, ScriptHtmlTagAttributes> _injectedScriptsFromURL = {};
|
||||
Set<WebMessageChannel> _webMessageChannels = Set();
|
||||
Set<WebMessageListener> _webMessageListeners = Set();
|
||||
|
||||
// static map that contains the properties to be saved and restored for keep alive feature
|
||||
static final Map<InAppWebViewKeepAlive, InAppWebViewControllerKeepAliveProps?>
|
||||
|
@ -86,17 +87,10 @@ class InAppWebViewController {
|
|||
|
||||
InAppWebViewController(dynamic id, WebView webview) {
|
||||
this._id = id;
|
||||
this._channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
if (_channel == null) return null;
|
||||
try {
|
||||
return await handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
channel = MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
|
||||
handler = handleMethod;
|
||||
initMethodCallHandler();
|
||||
|
||||
this._webview = webview;
|
||||
|
||||
final initialUserScripts = webview.initialUserScripts;
|
||||
|
@ -122,7 +116,7 @@ class InAppWebViewController {
|
|||
MethodChannel channel,
|
||||
InAppBrowser inAppBrowser,
|
||||
UnmodifiableListView<UserScript>? initialUserScripts) {
|
||||
this._channel = channel;
|
||||
this.channel = channel;
|
||||
this._inAppBrowser = inAppBrowser;
|
||||
|
||||
if (initialUserScripts != null) {
|
||||
|
@ -143,8 +137,8 @@ class InAppWebViewController {
|
|||
}
|
||||
|
||||
void _init() {
|
||||
android = AndroidInAppWebViewController(channel: _channel!);
|
||||
ios = IOSInAppWebViewController(channel: _channel!);
|
||||
android = AndroidInAppWebViewController(channel: channel!);
|
||||
ios = IOSInAppWebViewController(channel: channel!);
|
||||
webStorage = WebStorage(
|
||||
localStorage: LocalStorage(this), sessionStorage: SessionStorage(this));
|
||||
|
||||
|
@ -158,13 +152,17 @@ class InAppWebViewController {
|
|||
injectedScriptsFromURL: _injectedScriptsFromURL,
|
||||
javaScriptHandlersMap: _javaScriptHandlersMap,
|
||||
userScripts: _userScripts,
|
||||
webMessageListenerObjNames: _webMessageListenerObjNames);
|
||||
webMessageListenerObjNames: _webMessageListenerObjNames,
|
||||
webMessageChannels: _webMessageChannels,
|
||||
webMessageListeners: _webMessageListeners);
|
||||
} else {
|
||||
// restore controller properties
|
||||
_injectedScriptsFromURL = props.injectedScriptsFromURL;
|
||||
_javaScriptHandlersMap = props.javaScriptHandlersMap;
|
||||
_userScripts = props.userScripts;
|
||||
_webMessageListenerObjNames = props.webMessageListenerObjNames;
|
||||
_webMessageChannels = props.webMessageChannels;
|
||||
_webMessageListeners = props.webMessageListeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +178,7 @@ class InAppWebViewController {
|
|||
args: args);
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
if (WebView.debugLoggingSettings.enabled &&
|
||||
call.method != "onCallJsHandler") {
|
||||
_debugLog(call.method, call.arguments);
|
||||
|
@ -1430,7 +1428,7 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<WebUri?> getUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
String? url = await _channel?.invokeMethod('getUrl', args);
|
||||
String? url = await channel?.invokeMethod<String?>('getUrl', args);
|
||||
return url != null ? WebUri(url) : null;
|
||||
}
|
||||
|
||||
|
@ -1445,7 +1443,7 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<String?> getTitle() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getTitle', args);
|
||||
return await channel?.invokeMethod<String?>('getTitle', args);
|
||||
}
|
||||
|
||||
///Gets the progress for the current page. The progress value is between 0 and 100.
|
||||
|
@ -1456,7 +1454,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.estimatedProgress](https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress))
|
||||
Future<int?> getProgress() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getProgress', args);
|
||||
return await channel?.invokeMethod<int?>('getProgress', args);
|
||||
}
|
||||
|
||||
///Gets the content html of the page. It first tries to get the content through javascript.
|
||||
|
@ -1704,7 +1702,7 @@ class InAppWebViewController {
|
|||
Future<void> loadUrl(
|
||||
{required URLRequest urlRequest,
|
||||
@Deprecated('Use allowingReadAccessTo instead')
|
||||
Uri? iosAllowingReadAccessTo,
|
||||
Uri? iosAllowingReadAccessTo,
|
||||
WebUri? allowingReadAccessTo}) async {
|
||||
assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty);
|
||||
assert(
|
||||
|
@ -1719,7 +1717,7 @@ class InAppWebViewController {
|
|||
() =>
|
||||
allowingReadAccessTo?.toString() ??
|
||||
iosAllowingReadAccessTo?.toString());
|
||||
await _channel?.invokeMethod('loadUrl', args);
|
||||
await channel?.invokeMethod('loadUrl', args);
|
||||
}
|
||||
|
||||
///Loads the given [url] with [postData] (x-www-form-urlencoded) using `POST` method into this WebView.
|
||||
|
@ -1743,7 +1741,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url.toString());
|
||||
args.putIfAbsent('postData', () => postData);
|
||||
await _channel?.invokeMethod('postUrl', args);
|
||||
await channel?.invokeMethod('postUrl', args);
|
||||
}
|
||||
|
||||
///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content.
|
||||
|
@ -1770,11 +1768,10 @@ class InAppWebViewController {
|
|||
String mimeType = "text/html",
|
||||
String encoding = "utf8",
|
||||
WebUri? baseUrl,
|
||||
@Deprecated('Use historyUrl instead')
|
||||
Uri? androidHistoryUrl,
|
||||
@Deprecated('Use historyUrl instead') Uri? androidHistoryUrl,
|
||||
WebUri? historyUrl,
|
||||
@Deprecated('Use allowingReadAccessTo instead')
|
||||
Uri? iosAllowingReadAccessTo,
|
||||
Uri? iosAllowingReadAccessTo,
|
||||
WebUri? allowingReadAccessTo}) async {
|
||||
assert(
|
||||
allowingReadAccessTo == null || allowingReadAccessTo.isScheme("file"));
|
||||
|
@ -1797,7 +1794,7 @@ class InAppWebViewController {
|
|||
() =>
|
||||
allowingReadAccessTo?.toString() ??
|
||||
iosAllowingReadAccessTo?.toString());
|
||||
await _channel?.invokeMethod('loadData', args);
|
||||
await channel?.invokeMethod('loadData', args);
|
||||
}
|
||||
|
||||
///Loads the given [assetFilePath].
|
||||
|
@ -1839,7 +1836,7 @@ class InAppWebViewController {
|
|||
assert(assetFilePath.isNotEmpty);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('assetFilePath', () => assetFilePath);
|
||||
await _channel?.invokeMethod('loadFile', args);
|
||||
await channel?.invokeMethod('loadFile', args);
|
||||
}
|
||||
|
||||
///Reloads the WebView.
|
||||
|
@ -1853,7 +1850,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Location.reload](https://developer.mozilla.org/en-US/docs/Web/API/Location/reload))
|
||||
Future<void> reload() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('reload', args);
|
||||
await channel?.invokeMethod('reload', args);
|
||||
}
|
||||
|
||||
///Goes back in the history of the WebView.
|
||||
|
@ -1867,7 +1864,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - History.back](https://developer.mozilla.org/en-US/docs/Web/API/History/back))
|
||||
Future<void> goBack() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('goBack', args);
|
||||
await channel?.invokeMethod('goBack', args);
|
||||
}
|
||||
|
||||
///Returns a boolean value indicating whether the WebView can move backward.
|
||||
|
@ -1878,7 +1875,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.canGoBack](https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback))
|
||||
Future<bool> canGoBack() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('canGoBack', args);
|
||||
return await channel?.invokeMethod<bool>('canGoBack', args) ?? false;
|
||||
}
|
||||
|
||||
///Goes forward in the history of the WebView.
|
||||
|
@ -1892,7 +1889,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - History.forward](https://developer.mozilla.org/en-US/docs/Web/API/History/forward))
|
||||
Future<void> goForward() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('goForward', args);
|
||||
await channel?.invokeMethod('goForward', args);
|
||||
}
|
||||
|
||||
///Returns a boolean value indicating whether the WebView can move forward.
|
||||
|
@ -1903,7 +1900,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.canGoForward](https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward))
|
||||
Future<bool> canGoForward() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('canGoForward', args);
|
||||
return await channel?.invokeMethod<bool>('canGoForward', args) ?? false;
|
||||
}
|
||||
|
||||
///Goes to the history item that is the number of steps away from the current item. Steps is negative if backward and positive if forward.
|
||||
|
@ -1918,7 +1915,7 @@ class InAppWebViewController {
|
|||
Future<void> goBackOrForward({required int steps}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('steps', () => steps);
|
||||
await _channel?.invokeMethod('goBackOrForward', args);
|
||||
await channel?.invokeMethod('goBackOrForward', args);
|
||||
}
|
||||
|
||||
///Returns a boolean value indicating whether the WebView can go back or forward the given number of steps. Steps is negative if backward and positive if forward.
|
||||
|
@ -1930,7 +1927,8 @@ class InAppWebViewController {
|
|||
Future<bool> canGoBackOrForward({required int steps}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('steps', () => steps);
|
||||
return await _channel?.invokeMethod('canGoBackOrForward', args);
|
||||
return await channel?.invokeMethod<bool>('canGoBackOrForward', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///Navigates to a [WebHistoryItem] from the back-forward [WebHistory.list] and sets it as the current item.
|
||||
|
@ -1958,7 +1956,7 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<bool> isLoading() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isLoading', args);
|
||||
return await channel?.invokeMethod<bool>('isLoading', args) ?? false;
|
||||
}
|
||||
|
||||
///Stops the WebView from loading.
|
||||
|
@ -1972,7 +1970,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Window.stop](https://developer.mozilla.org/en-US/docs/Web/API/Window/stop))
|
||||
Future<void> stopLoading() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('stopLoading', args);
|
||||
await channel?.invokeMethod('stopLoading', args);
|
||||
}
|
||||
|
||||
///Evaluates JavaScript [source] code into the WebView and returns the result of the evaluation.
|
||||
|
@ -2002,7 +2000,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('source', () => source);
|
||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||
var data = await _channel?.invokeMethod('evaluateJavascript', args);
|
||||
var data = await channel?.invokeMethod('evaluateJavascript', args);
|
||||
if (data != null && (Util.isAndroid || Util.isWeb)) {
|
||||
try {
|
||||
// try to json decode the data coming from JavaScript
|
||||
|
@ -2041,7 +2039,7 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('urlFile', () => urlFile.toString());
|
||||
args.putIfAbsent(
|
||||
'scriptHtmlTagAttributes', () => scriptHtmlTagAttributes?.toMap());
|
||||
await _channel?.invokeMethod('injectJavascriptFileFromUrl', args);
|
||||
await channel?.invokeMethod('injectJavascriptFileFromUrl', args);
|
||||
}
|
||||
|
||||
///Evaluates the content of a JavaScript file into the WebView from the flutter assets directory.
|
||||
|
@ -2081,7 +2079,7 @@ class InAppWebViewController {
|
|||
Future<void> injectCSSCode({required String source}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('source', () => source);
|
||||
await _channel?.invokeMethod('injectCSSCode', args);
|
||||
await channel?.invokeMethod('injectCSSCode', args);
|
||||
}
|
||||
|
||||
///Injects an external CSS file into the WebView from a defined url.
|
||||
|
@ -2108,7 +2106,7 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('urlFile', () => urlFile.toString());
|
||||
args.putIfAbsent(
|
||||
'cssLinkHtmlTagAttributes', () => cssLinkHtmlTagAttributes?.toMap());
|
||||
await _channel?.invokeMethod('injectCSSFileFromUrl', args);
|
||||
await channel?.invokeMethod('injectCSSFileFromUrl', args);
|
||||
}
|
||||
|
||||
///Injects a CSS file into the WebView from the flutter assets directory.
|
||||
|
@ -2233,7 +2231,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent(
|
||||
'screenshotConfiguration', () => screenshotConfiguration?.toMap());
|
||||
return await _channel?.invokeMethod('takeScreenshot', args);
|
||||
return await channel?.invokeMethod<Uint8List?>('takeScreenshot', args);
|
||||
}
|
||||
|
||||
///Use [setSettings] instead.
|
||||
|
@ -2269,7 +2267,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
args.putIfAbsent('settings', () => settings.toMap());
|
||||
await _channel?.invokeMethod('setSettings', args);
|
||||
await channel?.invokeMethod('setSettings', args);
|
||||
}
|
||||
|
||||
///Gets the current WebView settings. Returns `null` if it wasn't able to get them.
|
||||
|
@ -2283,7 +2281,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
Map<dynamic, dynamic>? settings =
|
||||
await _channel?.invokeMethod('getSettings', args);
|
||||
await channel?.invokeMethod('getSettings', args);
|
||||
if (settings != null) {
|
||||
settings = settings.cast<String, dynamic>();
|
||||
return InAppWebViewSettings.fromMap(settings as Map<String, dynamic>);
|
||||
|
@ -2304,7 +2302,7 @@ class InAppWebViewController {
|
|||
Future<WebHistory?> getCopyBackForwardList() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? result =
|
||||
(await _channel?.invokeMethod('getCopyBackForwardList', args))
|
||||
(await channel?.invokeMethod('getCopyBackForwardList', args))
|
||||
?.cast<String, dynamic>();
|
||||
return WebHistory.fromMap(result);
|
||||
}
|
||||
|
@ -2317,7 +2315,7 @@ class InAppWebViewController {
|
|||
///- MacOS
|
||||
Future<void> clearCache() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('clearCache', args);
|
||||
await channel?.invokeMethod('clearCache', args);
|
||||
}
|
||||
|
||||
///Use [FindInteractionController.findAll] instead.
|
||||
|
@ -2325,7 +2323,7 @@ class InAppWebViewController {
|
|||
Future<void> findAllAsync({required String find}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('find', () => find);
|
||||
await _channel?.invokeMethod('findAll', args);
|
||||
await channel?.invokeMethod('findAll', args);
|
||||
}
|
||||
|
||||
///Use [FindInteractionController.findNext] instead.
|
||||
|
@ -2333,14 +2331,14 @@ class InAppWebViewController {
|
|||
Future<void> findNext({required bool forward}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('forward', () => forward);
|
||||
await _channel?.invokeMethod('findNext', args);
|
||||
await channel?.invokeMethod('findNext', args);
|
||||
}
|
||||
|
||||
///Use [FindInteractionController.clearMatches] instead.
|
||||
@Deprecated("Use FindInteractionController.clearMatches instead")
|
||||
Future<void> clearMatches() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('clearMatches', args);
|
||||
await channel?.invokeMethod('clearMatches', args);
|
||||
}
|
||||
|
||||
///Use [tRexRunnerHtml] instead.
|
||||
|
@ -2378,7 +2376,7 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('x', () => x);
|
||||
args.putIfAbsent('y', () => y);
|
||||
args.putIfAbsent('animated', () => animated);
|
||||
await _channel?.invokeMethod('scrollTo', args);
|
||||
await channel?.invokeMethod('scrollTo', args);
|
||||
}
|
||||
|
||||
///Moves the scrolled position of the WebView.
|
||||
|
@ -2404,7 +2402,7 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('x', () => x);
|
||||
args.putIfAbsent('y', () => y);
|
||||
args.putIfAbsent('animated', () => animated);
|
||||
await _channel?.invokeMethod('scrollBy', args);
|
||||
await channel?.invokeMethod('scrollBy', args);
|
||||
}
|
||||
|
||||
///On Android native WebView, it pauses all layout, parsing, and JavaScript timers for all WebViews.
|
||||
|
@ -2420,7 +2418,7 @@ class InAppWebViewController {
|
|||
///- MacOS
|
||||
Future<void> pauseTimers() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('pauseTimers', args);
|
||||
await channel?.invokeMethod('pauseTimers', args);
|
||||
}
|
||||
|
||||
///On Android, it resumes all layout, parsing, and JavaScript timers for all WebViews. This will resume dispatching all timers.
|
||||
|
@ -2435,7 +2433,7 @@ class InAppWebViewController {
|
|||
///- MacOS
|
||||
Future<void> resumeTimers() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('resumeTimers', args);
|
||||
await channel?.invokeMethod('resumeTimers', args);
|
||||
}
|
||||
|
||||
///Prints the current page.
|
||||
|
@ -2458,7 +2456,8 @@ class InAppWebViewController {
|
|||
{PrintJobSettings? settings}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("settings", () => settings?.toMap());
|
||||
String? jobId = await _channel?.invokeMethod('printCurrentPage', args);
|
||||
String? jobId =
|
||||
await channel?.invokeMethod<String?>('printCurrentPage', args);
|
||||
if (jobId != null) {
|
||||
return PrintJobController(id: jobId);
|
||||
}
|
||||
|
@ -2478,7 +2477,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Document.documentElement.scrollHeight](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight))
|
||||
Future<int?> getContentHeight() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
var height = await _channel?.invokeMethod('getContentHeight', args);
|
||||
var height = await channel?.invokeMethod('getContentHeight', args);
|
||||
if (height == null || height == 0) {
|
||||
// try to use javascript
|
||||
var scrollHeight = await evaluateJavascript(
|
||||
|
@ -2505,7 +2504,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Document.documentElement.scrollWidth](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth))
|
||||
Future<int?> getContentWidth() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
var height = await _channel?.invokeMethod('getContentWidth', args);
|
||||
var height = await channel?.invokeMethod('getContentWidth', args);
|
||||
if (height == null || height == 0) {
|
||||
// try to use javascript
|
||||
var scrollHeight = await evaluateJavascript(
|
||||
|
@ -2539,7 +2538,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('zoomFactor', () => zoomFactor);
|
||||
args.putIfAbsent('animated', () => iosAnimated ?? animated);
|
||||
return await _channel?.invokeMethod('zoomBy', args);
|
||||
return await channel?.invokeMethod('zoomBy', args);
|
||||
}
|
||||
|
||||
///Gets the URL that was originally requested for the current page.
|
||||
|
@ -2555,7 +2554,7 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<WebUri?> getOriginalUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
String? url = await _channel?.invokeMethod('getOriginalUrl', args);
|
||||
String? url = await channel?.invokeMethod<String?>('getOriginalUrl', args);
|
||||
return url != null ? WebUri(url) : null;
|
||||
}
|
||||
|
||||
|
@ -2566,7 +2565,7 @@ class InAppWebViewController {
|
|||
///- iOS ([Official API - UIScrollView.zoomScale](https://developer.apple.com/documentation/uikit/uiscrollview/1619419-zoomscale))
|
||||
Future<double?> getZoomScale() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getZoomScale', args);
|
||||
return await channel?.invokeMethod<double?>('getZoomScale', args);
|
||||
}
|
||||
|
||||
///Use [getZoomScale] instead.
|
||||
|
@ -2590,7 +2589,7 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<String?> getSelectedText() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getSelectedText', args);
|
||||
return await channel?.invokeMethod<String?>('getSelectedText', args);
|
||||
}
|
||||
|
||||
///Gets the hit result for hitting an HTML elements.
|
||||
|
@ -2603,7 +2602,7 @@ class InAppWebViewController {
|
|||
Future<InAppWebViewHitTestResult?> getHitTestResult() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<dynamic, dynamic>? hitTestResultMap =
|
||||
await _channel?.invokeMethod('getHitTestResult', args);
|
||||
await channel?.invokeMethod('getHitTestResult', args);
|
||||
|
||||
if (hitTestResultMap == null) {
|
||||
return null;
|
||||
|
@ -2625,7 +2624,7 @@ class InAppWebViewController {
|
|||
///- iOS ([Official API - UIResponder.resignFirstResponder](https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder))
|
||||
Future<void> clearFocus() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('clearFocus', args);
|
||||
return await channel?.invokeMethod('clearFocus', args);
|
||||
}
|
||||
|
||||
///Sets or updates the WebView context menu to be used next time it will appear.
|
||||
|
@ -2636,7 +2635,7 @@ class InAppWebViewController {
|
|||
Future<void> setContextMenu(ContextMenu? contextMenu) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("contextMenu", () => contextMenu?.toMap());
|
||||
await _channel?.invokeMethod('setContextMenu', args);
|
||||
await channel?.invokeMethod('setContextMenu', args);
|
||||
_inAppBrowser?.contextMenu = contextMenu;
|
||||
}
|
||||
|
||||
|
@ -2650,7 +2649,7 @@ class InAppWebViewController {
|
|||
Future<RequestFocusNodeHrefResult?> requestFocusNodeHref() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<dynamic, dynamic>? result =
|
||||
await _channel?.invokeMethod('requestFocusNodeHref', args);
|
||||
await channel?.invokeMethod('requestFocusNodeHref', args);
|
||||
return result != null
|
||||
? RequestFocusNodeHrefResult(
|
||||
url: result['url'] != null ? WebUri(result['url']) : null,
|
||||
|
@ -2670,7 +2669,7 @@ class InAppWebViewController {
|
|||
Future<RequestImageRefResult?> requestImageRef() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<dynamic, dynamic>? result =
|
||||
await _channel?.invokeMethod('requestImageRef', args);
|
||||
await channel?.invokeMethod('requestImageRef', args);
|
||||
return result != null
|
||||
? RequestImageRefResult(
|
||||
url: result['url'] != null ? WebUri(result['url']) : null,
|
||||
|
@ -2766,7 +2765,7 @@ class InAppWebViewController {
|
|||
try {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
themeColor = UtilColor.fromStringRepresentation(
|
||||
await _channel?.invokeMethod('getMetaThemeColor', args));
|
||||
await channel?.invokeMethod('getMetaThemeColor', args));
|
||||
return themeColor;
|
||||
} catch (e) {
|
||||
// not implemented
|
||||
|
@ -2809,7 +2808,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Window.scrollX](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollX))
|
||||
Future<int?> getScrollX() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getScrollX', args);
|
||||
return await channel?.invokeMethod<int?>('getScrollX', args);
|
||||
}
|
||||
|
||||
///Returns the scrolled top position of the current WebView.
|
||||
|
@ -2825,7 +2824,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Window.scrollY](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY))
|
||||
Future<int?> getScrollY() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getScrollY', args);
|
||||
return await channel?.invokeMethod<int?>('getScrollY', args);
|
||||
}
|
||||
|
||||
///Gets the SSL certificate for the main top-level page or null if there is no certificate (the site is not secure).
|
||||
|
@ -2837,7 +2836,7 @@ class InAppWebViewController {
|
|||
Future<SslCertificate?> getCertificate() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? sslCertificateMap =
|
||||
(await _channel?.invokeMethod('getCertificate', args))
|
||||
(await channel?.invokeMethod('getCertificate', args))
|
||||
?.cast<String, dynamic>();
|
||||
return SslCertificate.fromMap(sslCertificateMap);
|
||||
}
|
||||
|
@ -2860,7 +2859,7 @@ class InAppWebViewController {
|
|||
if (!(_userScripts[userScript.injectionTime]?.contains(userScript) ??
|
||||
false)) {
|
||||
_userScripts[userScript.injectionTime]?.add(userScript);
|
||||
await _channel?.invokeMethod('addUserScript', args);
|
||||
await channel?.invokeMethod('addUserScript', args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2906,7 +2905,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('userScript', () => userScript.toMap());
|
||||
args.putIfAbsent('index', () => index);
|
||||
await _channel?.invokeMethod('removeUserScript', args);
|
||||
await channel?.invokeMethod('removeUserScript', args);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2943,7 +2942,7 @@ class InAppWebViewController {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('groupName', () => groupName);
|
||||
await _channel?.invokeMethod('removeUserScriptsByGroupName', args);
|
||||
await channel?.invokeMethod('removeUserScriptsByGroupName', args);
|
||||
}
|
||||
|
||||
///Removes the [userScripts] from the webpage’s content.
|
||||
|
@ -2983,7 +2982,7 @@ class InAppWebViewController {
|
|||
_userScripts[UserScriptInjectionTime.AT_DOCUMENT_END]?.clear();
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('removeAllUserScripts', args);
|
||||
await channel?.invokeMethod('removeAllUserScripts', args);
|
||||
}
|
||||
|
||||
///Returns `true` if the [userScript] has been already added, otherwise `false`.
|
||||
|
@ -3038,7 +3037,7 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('functionBody', () => functionBody);
|
||||
args.putIfAbsent('arguments', () => arguments);
|
||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||
var data = await _channel?.invokeMethod('callAsyncJavaScript', args);
|
||||
var data = await channel?.invokeMethod('callAsyncJavaScript', args);
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -3081,7 +3080,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("filePath", () => filePath);
|
||||
args.putIfAbsent("autoname", () => autoname);
|
||||
return await _channel?.invokeMethod('saveWebArchive', args);
|
||||
return await channel?.invokeMethod<String?>('saveWebArchive', args);
|
||||
}
|
||||
|
||||
///Indicates whether the webpage context is capable of using features that require [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
|
||||
|
@ -3098,7 +3097,7 @@ class InAppWebViewController {
|
|||
///- Web ([Official API - Window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/API/Window/isSecureContext))
|
||||
Future<bool> isSecureContext() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isSecureContext', args);
|
||||
return await channel?.invokeMethod<bool>('isSecureContext', args) ?? false;
|
||||
}
|
||||
|
||||
///Creates a message channel to communicate with JavaScript and returns the message channel with ports that represent the endpoints of this message channel.
|
||||
|
@ -3121,9 +3120,13 @@ class InAppWebViewController {
|
|||
Future<WebMessageChannel?> createWebMessageChannel() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? result =
|
||||
(await _channel?.invokeMethod('createWebMessageChannel', args))
|
||||
(await channel?.invokeMethod('createWebMessageChannel', args))
|
||||
?.cast<String, dynamic>();
|
||||
return WebMessageChannel.fromMap(result);
|
||||
final webMessageChannel = WebMessageChannel.fromMap(result);
|
||||
if (webMessageChannel != null) {
|
||||
_webMessageChannels.add(webMessageChannel);
|
||||
}
|
||||
return webMessageChannel;
|
||||
}
|
||||
|
||||
///Post a message to main frame. The embedded application can restrict the messages to a certain target origin.
|
||||
|
@ -3149,7 +3152,7 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('message', () => message.toMap());
|
||||
args.putIfAbsent('targetOrigin', () => targetOrigin.toString());
|
||||
await _channel?.invokeMethod('postWebMessage', args);
|
||||
await channel?.invokeMethod('postWebMessage', args);
|
||||
}
|
||||
|
||||
///Adds a [WebMessageListener] to the WebView and injects a JavaScript object into each frame that the [WebMessageListener] will listen on.
|
||||
|
@ -3318,14 +3321,17 @@ class InAppWebViewController {
|
|||
///- MacOS
|
||||
Future<void> addWebMessageListener(
|
||||
WebMessageListener webMessageListener) async {
|
||||
assert(!_webMessageListeners.contains(webMessageListener),
|
||||
"${webMessageListener} was already added.");
|
||||
assert(
|
||||
!_webMessageListenerObjNames.contains(webMessageListener.jsObjectName),
|
||||
"jsObjectName ${webMessageListener.jsObjectName} was already added.");
|
||||
_webMessageListeners.add(webMessageListener);
|
||||
_webMessageListenerObjNames.add(webMessageListener.jsObjectName);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('webMessageListener', () => webMessageListener.toMap());
|
||||
await _channel?.invokeMethod('addWebMessageListener', args);
|
||||
await channel?.invokeMethod('addWebMessageListener', args);
|
||||
}
|
||||
|
||||
///Returns `true` if the [webMessageListener] has been already added, otherwise `false`.
|
||||
|
@ -3335,8 +3341,8 @@ class InAppWebViewController {
|
|||
///- iOS
|
||||
///- MacOS
|
||||
bool hasWebMessageListener(WebMessageListener webMessageListener) {
|
||||
return _webMessageListenerObjNames
|
||||
.contains(webMessageListener.jsObjectName);
|
||||
return _webMessageListeners.contains(webMessageListener) ||
|
||||
_webMessageListenerObjNames.contains(webMessageListener.jsObjectName);
|
||||
}
|
||||
|
||||
///Returns `true` if the webpage can scroll vertically, otherwise `false`.
|
||||
|
@ -3352,7 +3358,8 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<bool> canScrollVertically() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('canScrollVertically', args);
|
||||
return await channel?.invokeMethod<bool>('canScrollVertically', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///Returns `true` if the webpage can scroll horizontally, otherwise `false`.
|
||||
|
@ -3368,7 +3375,8 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<bool> canScrollHorizontally() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('canScrollHorizontally', args);
|
||||
return await channel?.invokeMethod<bool>('canScrollHorizontally', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///Starts Safe Browsing initialization.
|
||||
|
@ -3385,7 +3393,8 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.startSafeBrowsing](https://developer.android.com/reference/android/webkit/WebView#startSafeBrowsing(android.content.Context,%20android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)))
|
||||
Future<bool> startSafeBrowsing() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('startSafeBrowsing', args);
|
||||
return await channel?.invokeMethod<bool>('startSafeBrowsing', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
|
||||
|
@ -3394,7 +3403,7 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.clearSslPreferences](https://developer.android.com/reference/android/webkit/WebView#clearSslPreferences()))
|
||||
Future<void> clearSslPreferences() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('clearSslPreferences', args);
|
||||
await channel?.invokeMethod('clearSslPreferences', args);
|
||||
}
|
||||
|
||||
///Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
|
||||
|
@ -3404,7 +3413,7 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.onPause](https://developer.android.com/reference/android/webkit/WebView#onPause()))
|
||||
Future<void> pause() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('pause', args);
|
||||
await channel?.invokeMethod('pause', args);
|
||||
}
|
||||
|
||||
///Resumes a WebView after a previous call to [pause].
|
||||
|
@ -3413,7 +3422,7 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.onResume](https://developer.android.com/reference/android/webkit/WebView#onResume()))
|
||||
Future<void> resume() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('resume', args);
|
||||
await channel?.invokeMethod('resume', args);
|
||||
}
|
||||
|
||||
///Scrolls the contents of this WebView down by half the page size.
|
||||
|
@ -3426,7 +3435,7 @@ class InAppWebViewController {
|
|||
Future<bool> pageDown({required bool bottom}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("bottom", () => bottom);
|
||||
return await _channel?.invokeMethod('pageDown', args);
|
||||
return await channel?.invokeMethod<bool>('pageDown', args) ?? false;
|
||||
}
|
||||
|
||||
///Scrolls the contents of this WebView up by half the view size.
|
||||
|
@ -3439,7 +3448,7 @@ class InAppWebViewController {
|
|||
Future<bool> pageUp({required bool top}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("top", () => top);
|
||||
return await _channel?.invokeMethod('pageUp', args);
|
||||
return await channel?.invokeMethod<bool>('pageUp', args) ?? false;
|
||||
}
|
||||
|
||||
///Performs zoom in in this WebView.
|
||||
|
@ -3449,7 +3458,7 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.zoomIn](https://developer.android.com/reference/android/webkit/WebView#zoomIn()))
|
||||
Future<bool> zoomIn() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('zoomIn', args);
|
||||
return await channel?.invokeMethod<bool>('zoomIn', args) ?? false;
|
||||
}
|
||||
|
||||
///Performs zoom out in this WebView.
|
||||
|
@ -3459,7 +3468,7 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.zoomOut](https://developer.android.com/reference/android/webkit/WebView#zoomOut()))
|
||||
Future<bool> zoomOut() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('zoomOut', args);
|
||||
return await channel?.invokeMethod<bool>('zoomOut', args) ?? false;
|
||||
}
|
||||
|
||||
///Clears the internal back/forward list.
|
||||
|
@ -3468,7 +3477,7 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebView.clearHistory](https://developer.android.com/reference/android/webkit/WebView#clearHistory()))
|
||||
Future<void> clearHistory() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('clearHistory', args);
|
||||
return await channel?.invokeMethod('clearHistory', args);
|
||||
}
|
||||
|
||||
///Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.
|
||||
|
@ -3478,7 +3487,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.reloadFromOrigin](https://developer.apple.com/documentation/webkit/wkwebview/1414956-reloadfromorigin))
|
||||
Future<void> reloadFromOrigin() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('reloadFromOrigin', args);
|
||||
await channel?.invokeMethod('reloadFromOrigin', args);
|
||||
}
|
||||
|
||||
///Generates PDF data from the web view’s contents asynchronously.
|
||||
|
@ -3495,13 +3504,13 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.createPdf](https://developer.apple.com/documentation/webkit/wkwebview/3650490-createpdf))
|
||||
Future<Uint8List?> createPdf(
|
||||
{@Deprecated("Use pdfConfiguration instead")
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
IOSWKPDFConfiguration? iosWKPdfConfiguration,
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
IOSWKPDFConfiguration? iosWKPdfConfiguration,
|
||||
PDFConfiguration? pdfConfiguration}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('pdfConfiguration',
|
||||
() => pdfConfiguration?.toMap() ?? iosWKPdfConfiguration?.toMap());
|
||||
return await _channel?.invokeMethod('createPdf', args);
|
||||
return await channel?.invokeMethod<Uint8List?>('createPdf', args);
|
||||
}
|
||||
|
||||
///Creates a web archive of the web view’s current contents asynchronously.
|
||||
|
@ -3516,7 +3525,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.createWebArchiveData](https://developer.apple.com/documentation/webkit/wkwebview/3650491-createwebarchivedata))
|
||||
Future<Uint8List?> createWebArchiveData() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('createWebArchiveData', args);
|
||||
return await channel?.invokeMethod('createWebArchiveData', args);
|
||||
}
|
||||
|
||||
///A Boolean value indicating whether all resources on the page have been loaded over securely encrypted connections.
|
||||
|
@ -3526,7 +3535,8 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.hasOnlySecureContent](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent))
|
||||
Future<bool> hasOnlySecureContent() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('hasOnlySecureContent', args);
|
||||
return await channel?.invokeMethod<bool>('hasOnlySecureContent', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///Pauses playback of all media in the web view.
|
||||
|
@ -3540,7 +3550,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.pauseAllMediaPlayback](https://developer.apple.com/documentation/webkit/wkwebview/3752240-pauseallmediaplayback)).
|
||||
Future<void> pauseAllMediaPlayback() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('pauseAllMediaPlayback', args);
|
||||
return await channel?.invokeMethod('pauseAllMediaPlayback', args);
|
||||
}
|
||||
|
||||
///Changes whether the webpage is suspending playback of all media in the page.
|
||||
|
@ -3558,7 +3568,7 @@ class InAppWebViewController {
|
|||
Future<void> setAllMediaPlaybackSuspended({required bool suspended}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("suspended", () => suspended);
|
||||
return await _channel?.invokeMethod('setAllMediaPlaybackSuspended', args);
|
||||
return await channel?.invokeMethod('setAllMediaPlaybackSuspended', args);
|
||||
}
|
||||
|
||||
///Closes all media the web view is presenting, including picture-in-picture video and fullscreen video.
|
||||
|
@ -3572,7 +3582,7 @@ class InAppWebViewController {
|
|||
///- MacOS ([Official API - WKWebView.closeAllMediaPresentations](https://developer.apple.com/documentation/webkit/wkwebview/3752235-closeallmediapresentations)).
|
||||
Future<void> closeAllMediaPresentations() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('closeAllMediaPresentations', args);
|
||||
return await channel?.invokeMethod('closeAllMediaPresentations', args);
|
||||
}
|
||||
|
||||
///Requests the playback status of media in the web view.
|
||||
|
@ -3589,7 +3599,7 @@ class InAppWebViewController {
|
|||
Future<MediaPlaybackState?> requestMediaPlaybackState() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return MediaPlaybackState.fromNativeValue(
|
||||
await _channel?.invokeMethod('requestMediaPlaybackState', args));
|
||||
await channel?.invokeMethod('requestMediaPlaybackState', args));
|
||||
}
|
||||
|
||||
///Returns `true` if the [WebView] is in fullscreen mode, otherwise `false`.
|
||||
|
@ -3600,7 +3610,7 @@ class InAppWebViewController {
|
|||
///- MacOS
|
||||
Future<bool> isInFullscreen() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isInFullscreen', args);
|
||||
return await channel?.invokeMethod<bool>('isInFullscreen', args) ?? false;
|
||||
}
|
||||
|
||||
///Returns a [MediaCaptureState] that indicates whether the webpage is using the camera to capture images or video.
|
||||
|
@ -3615,7 +3625,7 @@ class InAppWebViewController {
|
|||
Future<MediaCaptureState?> getCameraCaptureState() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return MediaCaptureState.fromNativeValue(
|
||||
await _channel?.invokeMethod('getCameraCaptureState', args));
|
||||
await channel?.invokeMethod('getCameraCaptureState', args));
|
||||
}
|
||||
|
||||
///Changes whether the webpage is using the camera to capture images or video.
|
||||
|
@ -3630,7 +3640,7 @@ class InAppWebViewController {
|
|||
Future<void> setCameraCaptureState({required MediaCaptureState state}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('state', () => state.toNativeValue());
|
||||
await _channel?.invokeMethod('setCameraCaptureState', args);
|
||||
await channel?.invokeMethod('setCameraCaptureState', args);
|
||||
}
|
||||
|
||||
///Returns a [MediaCaptureState] that indicates whether the webpage is using the microphone to capture audio.
|
||||
|
@ -3645,7 +3655,7 @@ class InAppWebViewController {
|
|||
Future<MediaCaptureState?> getMicrophoneCaptureState() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return MediaCaptureState.fromNativeValue(
|
||||
await _channel?.invokeMethod('getMicrophoneCaptureState', args));
|
||||
await channel?.invokeMethod('getMicrophoneCaptureState', args));
|
||||
}
|
||||
|
||||
///Changes whether the webpage is using the microphone to capture audio.
|
||||
|
@ -3661,7 +3671,7 @@ class InAppWebViewController {
|
|||
{required MediaCaptureState state}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('state', () => state.toNativeValue());
|
||||
await _channel?.invokeMethod('setMicrophoneCaptureState', args);
|
||||
await channel?.invokeMethod('setMicrophoneCaptureState', args);
|
||||
}
|
||||
|
||||
///Loads the web content from the data you provide as if the data were the response to the request.
|
||||
|
@ -3697,7 +3707,7 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('urlRequest', () => urlRequest.toMap());
|
||||
args.putIfAbsent('data', () => data);
|
||||
args.putIfAbsent('urlResponse', () => urlResponse?.toMap());
|
||||
await _channel?.invokeMethod('loadSimulatedRequest', args);
|
||||
await channel?.invokeMethod('loadSimulatedRequest', args);
|
||||
}
|
||||
|
||||
///Returns the iframe `id` attribute used on the Web platform.
|
||||
|
@ -3706,7 +3716,7 @@ class InAppWebViewController {
|
|||
///- Web
|
||||
Future<String?> getIFrameId() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getIFrameId', args);
|
||||
return await channel?.invokeMethod<String?>('getIFrameId', args);
|
||||
}
|
||||
|
||||
///Gets the default user agent.
|
||||
|
@ -3717,7 +3727,9 @@ class InAppWebViewController {
|
|||
///- MacOS
|
||||
static Future<String> getDefaultUserAgent() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _staticChannel.invokeMethod('getDefaultUserAgent', args);
|
||||
return await _staticChannel.invokeMethod<String>(
|
||||
'getDefaultUserAgent', args) ??
|
||||
'';
|
||||
}
|
||||
|
||||
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
|
||||
|
@ -3777,7 +3789,9 @@ class InAppWebViewController {
|
|||
{required List<String> hosts}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('hosts', () => hosts);
|
||||
return await _staticChannel.invokeMethod('setSafeBrowsingAllowlist', args);
|
||||
return await _staticChannel.invokeMethod<bool>(
|
||||
'setSafeBrowsingAllowlist', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///If WebView has already been loaded into the current process this method will return the package that was used to load it.
|
||||
|
@ -3833,7 +3847,8 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebViewCompat.getVariationsHeader](https://developer.android.com/reference/androidx/webkit/WebViewCompat#getVariationsHeader()))
|
||||
static Future<String?> getVariationsHeader() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _staticChannel.invokeMethod('getVariationsHeader', args);
|
||||
return await _staticChannel.invokeMethod<String?>(
|
||||
'getVariationsHeader', args);
|
||||
}
|
||||
|
||||
///Returns `true` if WebView is running in multi process mode.
|
||||
|
@ -3850,7 +3865,9 @@ class InAppWebViewController {
|
|||
///- Android native WebView ([Official API - WebViewCompat.isMultiProcessEnabled](https://developer.android.com/reference/androidx/webkit/WebViewCompat#isMultiProcessEnabled()))
|
||||
static Future<bool> isMultiProcessEnabled() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _staticChannel.invokeMethod('isMultiProcessEnabled', args);
|
||||
return await _staticChannel.invokeMethod<bool>(
|
||||
'isMultiProcessEnabled', args) ??
|
||||
false;
|
||||
}
|
||||
|
||||
///Returns a Boolean value that indicates whether WebKit natively supports resources with the specified URL scheme.
|
||||
|
@ -3901,24 +3918,17 @@ class InAppWebViewController {
|
|||
static Future<String> get tRexRunnerCss async => await rootBundle.loadString(
|
||||
'packages/flutter_inappwebview/assets/t_rex_runner/t-rex.css');
|
||||
|
||||
///Used internally.
|
||||
MethodChannel? getChannel() {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
///Used internally.
|
||||
///View ID used internally.
|
||||
dynamic getViewId() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
///Disposes the controller.
|
||||
@override
|
||||
void dispose({bool isKeepAlive = false}) {
|
||||
if (!isKeepAlive) {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
}
|
||||
disposeChannel(removeMethodCallHandler: !isKeepAlive);
|
||||
android.dispose();
|
||||
ios.dispose();
|
||||
_channel = null;
|
||||
_webview = null;
|
||||
_inAppBrowser = null;
|
||||
webStorage.dispose();
|
||||
|
@ -3927,6 +3937,18 @@ class InAppWebViewController {
|
|||
_userScripts.clear();
|
||||
_webMessageListenerObjNames.clear();
|
||||
_injectedScriptsFromURL.clear();
|
||||
for (final webMessageChannel in _webMessageChannels) {
|
||||
webMessageChannel.dispose();
|
||||
}
|
||||
_webMessageChannels.clear();
|
||||
for (final webMessageListener in _webMessageListeners) {
|
||||
webMessageListener.dispose();
|
||||
}
|
||||
_webMessageListeners.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension InternalInAppWebViewController on InAppWebViewController {
|
||||
get handleMethod => _handleMethod;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import '../types/main.dart';
|
||||
import '../util.dart';
|
||||
import '../web_message/web_message_channel.dart';
|
||||
import '../web_message/web_message_listener.dart';
|
||||
import 'in_app_webview.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
|
||||
|
@ -24,10 +26,14 @@ class InAppWebViewControllerKeepAliveProps {
|
|||
Map<UserScriptInjectionTime, List<UserScript>> userScripts;
|
||||
Set<String> webMessageListenerObjNames;
|
||||
Map<String, ScriptHtmlTagAttributes> injectedScriptsFromURL;
|
||||
Set<WebMessageChannel> webMessageChannels = Set();
|
||||
Set<WebMessageListener> webMessageListeners = Set();
|
||||
|
||||
InAppWebViewControllerKeepAliveProps(
|
||||
{required this.javaScriptHandlersMap,
|
||||
required this.userScripts,
|
||||
required this.webMessageListenerObjNames,
|
||||
required this.injectedScriptsFromURL});
|
||||
required this.injectedScriptsFromURL,
|
||||
required this.webMessageChannels,
|
||||
required this.webMessageListeners});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export 'webview.dart';
|
||||
export 'in_app_webview.dart';
|
||||
export 'in_app_webview_controller.dart';
|
||||
export 'in_app_webview_controller.dart' hide InternalInAppWebViewController;
|
||||
export 'in_app_webview_settings.dart'
|
||||
show
|
||||
InAppWebViewSettings,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/src/util.dart';
|
||||
import '../types/print_job_info.dart';
|
||||
import '../in_app_webview/in_app_webview_controller.dart';
|
||||
import '../types/disposable.dart';
|
||||
|
||||
///A completion handler for the [PrintJobController].
|
||||
typedef PrintJobCompletionHandler = Future<void> Function(
|
||||
|
@ -13,12 +13,10 @@ typedef PrintJobCompletionHandler = Future<void> Function(
|
|||
///- Android native WebView
|
||||
///- iOS
|
||||
///- MacOS
|
||||
class PrintJobController implements Disposable {
|
||||
class PrintJobController extends ChannelController {
|
||||
///Print job ID.
|
||||
final String id;
|
||||
|
||||
MethodChannel? _channel;
|
||||
|
||||
///A completion handler used to handle the conclusion of the print job (for instance, to reset state) and to handle any errors encountered in printing.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
|
@ -27,16 +25,10 @@ class PrintJobController implements Disposable {
|
|||
PrintJobCompletionHandler onComplete;
|
||||
|
||||
PrintJobController({required this.id}) {
|
||||
this._channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_printjobcontroller_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
|
@ -60,7 +52,7 @@ class PrintJobController implements Disposable {
|
|||
///- Android native WebView ([Official API - PrintJob.cancel](https://developer.android.com/reference/android/print/PrintJob#cancel()))
|
||||
Future<void> cancel() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('cancel', args);
|
||||
await channel?.invokeMethod('cancel', args);
|
||||
}
|
||||
|
||||
///Restarts this print job.
|
||||
|
@ -70,7 +62,7 @@ class PrintJobController implements Disposable {
|
|||
///- Android native WebView ([Official API - PrintJob.restart](https://developer.android.com/reference/android/print/PrintJob#restart()))
|
||||
Future<void> restart() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('restart', args);
|
||||
await channel?.invokeMethod('restart', args);
|
||||
}
|
||||
|
||||
///Dismisses the printing-options sheet or popover.
|
||||
|
@ -85,7 +77,7 @@ class PrintJobController implements Disposable {
|
|||
Future<void> dismiss({bool animated: true}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("animated", () => animated);
|
||||
await _channel?.invokeMethod('dismiss', args);
|
||||
await channel?.invokeMethod('dismiss', args);
|
||||
}
|
||||
|
||||
///Gets the [PrintJobInfo] that describes this job.
|
||||
|
@ -101,7 +93,7 @@ class PrintJobController implements Disposable {
|
|||
Future<PrintJobInfo?> getInfo() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? infoMap =
|
||||
(await _channel?.invokeMethod('getInfo', args))
|
||||
(await channel?.invokeMethod('getInfo', args))
|
||||
?.cast<String, dynamic>();
|
||||
return PrintJobInfo.fromMap(infoMap);
|
||||
}
|
||||
|
@ -115,8 +107,7 @@ class PrintJobController implements Disposable {
|
|||
@override
|
||||
Future<void> dispose() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod('dispose', args);
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
await channel?.invokeMethod('dispose', args);
|
||||
disposeChannel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,11 @@ import '../debug_logging_settings.dart';
|
|||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
class PullToRefreshController {
|
||||
class PullToRefreshController extends ChannelController {
|
||||
@Deprecated("Use settings instead")
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
late PullToRefreshOptions options;
|
||||
late PullToRefreshSettings settings;
|
||||
MethodChannel? _channel;
|
||||
|
||||
///Debug settings.
|
||||
static DebugLoggingSettings debugLoggingSettings = DebugLoggingSettings();
|
||||
|
@ -73,7 +72,7 @@ class PullToRefreshController {
|
|||
Future<void> setEnabled(bool enabled) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('enabled', () => enabled);
|
||||
await _channel?.invokeMethod('setEnabled', args);
|
||||
await channel?.invokeMethod('setEnabled', args);
|
||||
}
|
||||
|
||||
///Returns `true` is pull-to-refresh feature is enabled, otherwise `false`.
|
||||
|
@ -83,13 +82,13 @@ class PullToRefreshController {
|
|||
///- iOS ([Official API - UIScrollView.refreshControl](https://developer.apple.com/documentation/uikit/uiscrollview/2127691-refreshcontrol))
|
||||
Future<bool> isEnabled() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isEnabled', args);
|
||||
return await channel?.invokeMethod<bool>('isEnabled', args) ?? false;
|
||||
}
|
||||
|
||||
Future<void> _setRefreshing(bool refreshing) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('refreshing', () => refreshing);
|
||||
await _channel?.invokeMethod('setRefreshing', args);
|
||||
await channel?.invokeMethod('setRefreshing', args);
|
||||
}
|
||||
|
||||
///Tells the controller that a refresh operation was started programmatically.
|
||||
|
@ -126,7 +125,7 @@ class PullToRefreshController {
|
|||
///- iOS ([Official API - UIRefreshControl.isRefreshing](https://developer.apple.com/documentation/uikit/uirefreshcontrol/1624844-isrefreshing))
|
||||
Future<bool> isRefreshing() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('isRefreshing', args);
|
||||
return await channel?.invokeMethod<bool>('isRefreshing', args) ?? false;
|
||||
}
|
||||
|
||||
///Sets the color of the refresh control.
|
||||
|
@ -137,7 +136,7 @@ class PullToRefreshController {
|
|||
Future<void> setColor(Color color) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('color', () => color.toHex());
|
||||
await _channel?.invokeMethod('setColor', args);
|
||||
await channel?.invokeMethod('setColor', args);
|
||||
}
|
||||
|
||||
///Sets the background color of the refresh control.
|
||||
|
@ -148,7 +147,7 @@ class PullToRefreshController {
|
|||
Future<void> setBackgroundColor(Color color) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('color', () => color.toHex());
|
||||
await _channel?.invokeMethod('setBackgroundColor', args);
|
||||
await channel?.invokeMethod('setBackgroundColor', args);
|
||||
}
|
||||
|
||||
///Set the distance to trigger a sync in dips.
|
||||
|
@ -158,7 +157,7 @@ class PullToRefreshController {
|
|||
Future<void> setDistanceToTriggerSync(int distanceToTriggerSync) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('distanceToTriggerSync', () => distanceToTriggerSync);
|
||||
await _channel?.invokeMethod('setDistanceToTriggerSync', args);
|
||||
await channel?.invokeMethod('setDistanceToTriggerSync', args);
|
||||
}
|
||||
|
||||
///Sets the distance that the refresh indicator can be pulled beyond its resting position during a swipe gesture.
|
||||
|
@ -168,7 +167,7 @@ class PullToRefreshController {
|
|||
Future<void> setSlingshotDistance(int slingshotDistance) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('slingshotDistance', () => slingshotDistance);
|
||||
await _channel?.invokeMethod('setSlingshotDistance', args);
|
||||
await channel?.invokeMethod('setSlingshotDistance', args);
|
||||
}
|
||||
|
||||
///Gets the default distance that the refresh indicator can be pulled beyond its resting position during a swipe gesture.
|
||||
|
@ -177,7 +176,7 @@ class PullToRefreshController {
|
|||
///- Android native WebView ([Official API - SwipeRefreshLayout.DEFAULT_SLINGSHOT_DISTANCE](https://developer.android.com/reference/androidx/swiperefreshlayout/widget/SwipeRefreshLayout#DEFAULT_SLINGSHOT_DISTANCE()))
|
||||
Future<int> getDefaultSlingshotDistance() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('getDefaultSlingshotDistance', args);
|
||||
return await channel?.invokeMethod<int>('getDefaultSlingshotDistance', args) ?? 0;
|
||||
}
|
||||
|
||||
///Use [setIndicatorSize] instead.
|
||||
|
@ -185,7 +184,7 @@ class PullToRefreshController {
|
|||
Future<void> setSize(AndroidPullToRefreshSize size) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('size', () => size.toNativeValue());
|
||||
await _channel?.invokeMethod('setSize', args);
|
||||
await channel?.invokeMethod('setSize', args);
|
||||
}
|
||||
|
||||
///Sets the size of the refresh indicator. One of [PullToRefreshSize.DEFAULT], or [PullToRefreshSize.LARGE].
|
||||
|
@ -195,7 +194,7 @@ class PullToRefreshController {
|
|||
Future<void> setIndicatorSize(PullToRefreshSize size) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('size', () => size.toNativeValue());
|
||||
await _channel?.invokeMethod('setSize', args);
|
||||
await channel?.invokeMethod('setSize', args);
|
||||
}
|
||||
|
||||
///Use [setStyledTitle] instead.
|
||||
|
@ -203,7 +202,7 @@ class PullToRefreshController {
|
|||
Future<void> setAttributedTitle(IOSNSAttributedString attributedTitle) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('attributedTitle', () => attributedTitle.toMap());
|
||||
await _channel?.invokeMethod('setStyledTitle', args);
|
||||
await channel?.invokeMethod('setStyledTitle', args);
|
||||
}
|
||||
|
||||
///Sets the styled title text to display in the refresh control.
|
||||
|
@ -213,30 +212,21 @@ class PullToRefreshController {
|
|||
Future<void> setStyledTitle(AttributedString attributedTitle) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('attributedTitle', () => attributedTitle.toMap());
|
||||
await _channel?.invokeMethod('setStyledTitle', args);
|
||||
await channel?.invokeMethod('setStyledTitle', args);
|
||||
}
|
||||
|
||||
///Disposes the controller.
|
||||
@override
|
||||
void dispose({bool isKeepAlive = false}) {
|
||||
if (!isKeepAlive) {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
}
|
||||
_channel = null;
|
||||
disposeChannel(removeMethodCallHandler: !isKeepAlive);
|
||||
}
|
||||
}
|
||||
|
||||
extension InternalPullToRefreshController on PullToRefreshController {
|
||||
void init(dynamic id) {
|
||||
this._channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
if (_channel == null) return null;
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'debug_logging_settings.dart';
|
||||
import 'types/disposable.dart';
|
||||
|
||||
class Util {
|
||||
static bool get isWeb => kIsWeb;
|
||||
|
@ -582,3 +584,60 @@ void debugLog(
|
|||
class Color_ extends Color {
|
||||
Color_(int value) : super(value);
|
||||
}
|
||||
|
||||
abstract class ChannelController implements Disposable {
|
||||
MethodChannel? _channel;
|
||||
Future<dynamic> Function(MethodCall call)? _handler;
|
||||
|
||||
static bool debugAssertNotDisposed(ChannelController controller) {
|
||||
assert(() {
|
||||
if (controller.disposed) {
|
||||
throw FlutterError(
|
||||
'A ${controller.runtimeType} was used after being disposed.\n'
|
||||
'Once the ${controller.runtimeType} has been disposed, it '
|
||||
'can no longer be used.',
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
extension InternalChannelController on ChannelController {
|
||||
set channel (MethodChannel? channel) => _channel = channel;
|
||||
|
||||
MethodChannel? get channel {
|
||||
assert(ChannelController.debugAssertNotDisposed(this));
|
||||
return this._channel;
|
||||
}
|
||||
|
||||
set handler (Future<dynamic> Function(MethodCall call)? handler) => _handler = handler;
|
||||
|
||||
Future<dynamic> Function(MethodCall call)? get handler => _handler;
|
||||
|
||||
bool get disposed => _channel == null;
|
||||
|
||||
initMethodCallHandler() {
|
||||
assert(channel != null, 'Method Channel for ${runtimeType} not initialized!');
|
||||
assert(handler != null, 'Method Call Handler for ${runtimeType} not initialized!');
|
||||
|
||||
channel?.setMethodCallHandler((call) async {
|
||||
if (disposed) return null;
|
||||
try {
|
||||
return await handler!(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
disposeChannel({bool removeMethodCallHandler = true}) {
|
||||
if (removeMethodCallHandler) {
|
||||
channel?.setMethodCallHandler(null);
|
||||
}
|
||||
channel = null;
|
||||
handler = null;
|
||||
}
|
||||
}
|
|
@ -5,13 +5,11 @@ import 'package:flutter/services.dart';
|
|||
import 'headless_inappwebview_manager.dart';
|
||||
import 'in_app_web_view_web_element.dart';
|
||||
import '../util.dart';
|
||||
import '../types/disposable.dart';
|
||||
|
||||
class HeadlessInAppWebViewWebElement implements Disposable {
|
||||
class HeadlessInAppWebViewWebElement extends ChannelController {
|
||||
String id;
|
||||
late BinaryMessenger _messenger;
|
||||
InAppWebViewWebElement? webView;
|
||||
late MethodChannel? _channel;
|
||||
|
||||
HeadlessInAppWebViewWebElement(
|
||||
{required this.id,
|
||||
|
@ -19,23 +17,16 @@ class HeadlessInAppWebViewWebElement implements Disposable {
|
|||
required this.webView}) {
|
||||
this._messenger = messenger;
|
||||
|
||||
_channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_headless_inappwebview_${this.id}',
|
||||
const StandardMethodCodec(),
|
||||
_messenger,
|
||||
);
|
||||
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await handleMethodCall(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethodCall(MethodCall call) async {
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case "dispose":
|
||||
dispose();
|
||||
|
@ -57,7 +48,7 @@ class HeadlessInAppWebViewWebElement implements Disposable {
|
|||
}
|
||||
|
||||
void onWebViewCreated() async {
|
||||
await _channel?.invokeMethod("onWebViewCreated");
|
||||
await channel?.invokeMethod("onWebViewCreated");
|
||||
}
|
||||
|
||||
void setSize(Size size) {
|
||||
|
@ -73,8 +64,7 @@ class HeadlessInAppWebViewWebElement implements Disposable {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
disposeChannel();
|
||||
HeadlessInAppWebViewManager.webViews.putIfAbsent(id, () => null);
|
||||
webView?.dispose();
|
||||
webView = null;
|
||||
|
|
|
@ -1,35 +1,27 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/src/util.dart';
|
||||
|
||||
import 'dart:js' as js;
|
||||
|
||||
import 'web_platform_manager.dart';
|
||||
import '../types/disposable.dart';
|
||||
|
||||
class PlatformUtil implements Disposable {
|
||||
class PlatformUtil extends ChannelController {
|
||||
late BinaryMessenger _messenger;
|
||||
late MethodChannel? _channel;
|
||||
|
||||
PlatformUtil({required BinaryMessenger messenger}) {
|
||||
this._messenger = messenger;
|
||||
|
||||
_channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_platformutil',
|
||||
const StandardMethodCodec(),
|
||||
_messenger,
|
||||
);
|
||||
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await handleMethodCall(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethodCall(MethodCall call) async {
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case "getWebCookieExpirationDate":
|
||||
int timestamp = call.arguments['date'];
|
||||
|
@ -51,7 +43,6 @@ class PlatformUtil implements Disposable {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
disposeChannel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import '../util.dart';
|
||||
import '../debug_logging_settings.dart';
|
||||
import '../types/main.dart';
|
||||
import '../types/disposable.dart';
|
||||
|
||||
import '../web_uri.dart';
|
||||
import 'web_authenticate_session_settings.dart';
|
||||
|
@ -37,7 +35,7 @@ typedef WebAuthenticationSessionCompletionHandler = Future<void> Function(
|
|||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
///- MacOS
|
||||
class WebAuthenticationSession implements Disposable {
|
||||
class WebAuthenticationSession extends ChannelController {
|
||||
///Debug settings.
|
||||
static DebugLoggingSettings debugLoggingSettings = DebugLoggingSettings();
|
||||
|
||||
|
@ -56,7 +54,6 @@ class WebAuthenticationSession implements Disposable {
|
|||
///A completion handler the session calls when it completes successfully, or when the user cancels the session.
|
||||
WebAuthenticationSessionCompletionHandler onComplete;
|
||||
|
||||
MethodChannel? _channel;
|
||||
static const MethodChannel _sharedChannel = const MethodChannel(
|
||||
'com.pichillilorenzo/flutter_webauthenticationsession');
|
||||
|
||||
|
@ -102,16 +99,10 @@ class WebAuthenticationSession implements Disposable {
|
|||
id = IdGenerator.generate();
|
||||
this.initialSettings =
|
||||
initialSettings ?? WebAuthenticationSessionSettings();
|
||||
this._channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_webauthenticationsession_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
_debugLog(String method, dynamic args) {
|
||||
|
@ -147,7 +138,7 @@ class WebAuthenticationSession implements Disposable {
|
|||
///- iOS ([Official API - ASWebAuthenticationSession.canStart](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/3516277-canstart))
|
||||
Future<bool> canStart() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('canStart', args);
|
||||
return await channel?.invokeMethod<bool>('canStart', args) ?? false;
|
||||
}
|
||||
|
||||
///Starts the web authentication session.
|
||||
|
@ -161,7 +152,7 @@ class WebAuthenticationSession implements Disposable {
|
|||
///- iOS ([Official API - ASWebAuthenticationSession.start](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990953-start))
|
||||
Future<bool> start() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel?.invokeMethod('start', args);
|
||||
return await channel?.invokeMethod<bool>('start', args) ?? false;
|
||||
}
|
||||
|
||||
///Cancels the web authentication session.
|
||||
|
@ -173,7 +164,7 @@ class WebAuthenticationSession implements Disposable {
|
|||
///- iOS ([Official API - ASWebAuthenticationSession.cancel](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990951-cancel))
|
||||
Future<void> cancel() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod("cancel", args);
|
||||
await channel?.invokeMethod("cancel", args);
|
||||
}
|
||||
|
||||
///Disposes the web authentication session.
|
||||
|
@ -183,9 +174,8 @@ class WebAuthenticationSession implements Disposable {
|
|||
@override
|
||||
Future<void> dispose() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel?.invokeMethod("dispose", args);
|
||||
_channel?.setMethodCallHandler(null);
|
||||
_channel = null;
|
||||
await channel?.invokeMethod("dispose", args);
|
||||
disposeChannel();
|
||||
}
|
||||
|
||||
///Returns `true` if [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession)
|
||||
|
@ -196,6 +186,6 @@ class WebAuthenticationSession implements Disposable {
|
|||
///- iOS
|
||||
static Future<bool> isAvailable() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _sharedChannel.invokeMethod("isAvailable", args);
|
||||
return await _sharedChannel.invokeMethod<bool>("isAvailable", args) ?? false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/src/util.dart';
|
||||
import 'web_message_port.dart';
|
||||
|
||||
///The representation of the [HTML5 message channels](https://html.spec.whatwg.org/multipage/web-messaging.html#message-channels).
|
||||
|
@ -7,7 +8,7 @@ import 'web_message_port.dart';
|
|||
///- Android native WebView
|
||||
///- iOS
|
||||
///- MacOS
|
||||
class WebMessageChannel {
|
||||
class WebMessageChannel extends ChannelController {
|
||||
///Message Channel ID used internally.
|
||||
final String id;
|
||||
|
||||
|
@ -17,20 +18,12 @@ class WebMessageChannel {
|
|||
///The second [WebMessagePort] object of the channel.
|
||||
final WebMessagePort port2;
|
||||
|
||||
MethodChannel? _channel;
|
||||
|
||||
WebMessageChannel(
|
||||
{required this.id, required this.port1, required this.port2}) {
|
||||
this._channel = MethodChannel(
|
||||
channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_web_message_channel_$id');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
static WebMessageChannel? fromMap(Map<String, dynamic>? map) {
|
||||
|
@ -62,6 +55,12 @@ class WebMessageChannel {
|
|||
return null;
|
||||
}
|
||||
|
||||
///Disposes the web message channel.
|
||||
@override
|
||||
void dispose() {
|
||||
disposeChannel();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WebMessageChannel{id: $id, port1: $port1, port2: $port2}';
|
||||
|
@ -69,5 +68,5 @@ class WebMessageChannel {
|
|||
}
|
||||
|
||||
extension InternalWebMessageChannel on WebMessageChannel {
|
||||
MethodChannel? get channel => _channel;
|
||||
MethodChannel? get internalChannel => channel;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import '../web_uri.dart';
|
|||
///- Android native WebView
|
||||
///- iOS
|
||||
///- MacOS
|
||||
class WebMessageListener {
|
||||
class WebMessageListener extends ChannelController {
|
||||
///Message Listener ID used internally.
|
||||
late final String id;
|
||||
|
||||
|
@ -34,8 +34,6 @@ class WebMessageListener {
|
|||
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewCompat.WebMessageListener#onPostMessage(android.webkit.WebView,%20androidx.webkit.WebMessageCompat,%20android.net.Uri,%20boolean,%20androidx.webkit.JavaScriptReplyProxy)
|
||||
OnPostMessageCallback? onPostMessage;
|
||||
|
||||
MethodChannel? _channel;
|
||||
|
||||
WebMessageListener(
|
||||
{required this.jsObjectName,
|
||||
Set<String>? allowedOriginRules,
|
||||
|
@ -45,16 +43,10 @@ class WebMessageListener {
|
|||
allowedOriginRules != null ? allowedOriginRules : Set.from(["*"]);
|
||||
assert(!this.allowedOriginRules.contains(""),
|
||||
"allowedOriginRules cannot contain empty strings");
|
||||
this._channel = MethodChannel(
|
||||
channel= MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_web_message_listener_${id}_$jsObjectName');
|
||||
this._channel?.setMethodCallHandler((call) async {
|
||||
try {
|
||||
return await _handleMethod(call);
|
||||
} on Error catch (e) {
|
||||
print(e);
|
||||
print(e.stackTrace);
|
||||
}
|
||||
});
|
||||
handler = _handleMethod;
|
||||
initMethodCallHandler();
|
||||
}
|
||||
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
|
@ -78,6 +70,11 @@ class WebMessageListener {
|
|||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
disposeChannel();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"id": id,
|
||||
|
@ -114,7 +111,7 @@ class JavaScriptReplyProxy {
|
|||
Future<void> postMessage(String message) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('message', () => message);
|
||||
await _webMessageListener._channel?.invokeMethod('postMessage', args);
|
||||
await _webMessageListener.channel?.invokeMethod('postMessage', args);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -37,7 +37,7 @@ class WebMessagePort {
|
|||
Future<void> setWebMessageCallback(WebMessageCallback? onMessage) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('index', () => this._index);
|
||||
await _webMessageChannel.channel
|
||||
await _webMessageChannel.internalChannel
|
||||
?.invokeMethod('setWebMessageCallback', args);
|
||||
this._onMessage = onMessage;
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ class WebMessagePort {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('index', () => this._index);
|
||||
args.putIfAbsent('message', () => message.toMap());
|
||||
await _webMessageChannel.channel?.invokeMethod('postMessage', args);
|
||||
await _webMessageChannel.internalChannel?.invokeMethod('postMessage', args);
|
||||
}
|
||||
|
||||
///Close the message port and free any resources associated with it.
|
||||
Future<void> close() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('index', () => this._index);
|
||||
await _webMessageChannel.channel?.invokeMethod('close', args);
|
||||
await _webMessageChannel.internalChannel?.invokeMethod('close', args);
|
||||
}
|
||||
|
||||
@ExchangeableObjectMethod(toMapMergeWith: true)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import '../in_app_webview/in_app_webview_controller.dart';
|
||||
import '../types/disposable.dart';
|
||||
import '../types/main.dart';
|
||||
import 'web_storage_item.dart';
|
||||
|
||||
|
@ -12,7 +13,7 @@ import 'web_storage_item.dart';
|
|||
///- iOS
|
||||
///- MacOS
|
||||
///- Web
|
||||
class WebStorage {
|
||||
class WebStorage implements Disposable {
|
||||
///Represents `window.localStorage`.
|
||||
LocalStorage localStorage;
|
||||
|
||||
|
@ -22,6 +23,7 @@ class WebStorage {
|
|||
WebStorage({required this.localStorage, required this.sessionStorage});
|
||||
|
||||
///Disposes the web storage.
|
||||
@override
|
||||
void dispose() {
|
||||
localStorage.dispose();
|
||||
sessionStorage.dispose();
|
||||
|
@ -30,7 +32,7 @@ class WebStorage {
|
|||
|
||||
///Class that provides methods to manage the JavaScript [Storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) object.
|
||||
///It is used by [LocalStorage] and [SessionStorage].
|
||||
class Storage {
|
||||
class Storage implements Disposable {
|
||||
InAppWebViewController? _controller;
|
||||
|
||||
///The web storage type: `window.sessionStorage` or `window.localStorage`.
|
||||
|
@ -179,6 +181,7 @@ class Storage {
|
|||
}
|
||||
|
||||
///Disposes the storage.
|
||||
@override
|
||||
void dispose() {
|
||||
_controller = null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue