added HeadlessInAppWebView class, added close, addMenuItem and addMenuItems methods to ChromeSafariBrowser, added ChromeSafariBrowserMenuItem class, fixed InAppWebView.channel null exception on android, fix #305, fix #245, fix #299
This commit is contained in:
parent
f9ed06cc02
commit
02c3de9280
|
@ -1,5 +1,11 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="OTHER_INDENT_OPTIONS">
|
||||
<value>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</value>
|
||||
</option>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownEnhProjectSettings">
|
||||
<AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" />
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imagePathType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
<component name="MarkdownNavigatorHistory">
|
||||
<PasteImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
|
||||
<highlightList />
|
||||
<directories />
|
||||
<filenames />
|
||||
</PasteImageHistory>
|
||||
<CopyImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
|
||||
<highlightList />
|
||||
<directories />
|
||||
<filenames />
|
||||
</CopyImageHistory>
|
||||
<PasteLinkHistory onPasteImageTargetRef="3" onPasteTargetRef="1" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteWikiElement="2" onPasteReferenceElement="2" hideInapplicableOperations="false" preserveLinkFormat="false" useHeadingForLinkText="false" linkFormat="0" saveAsDefaultOnOK="false" />
|
||||
<TableToJsonHistory>
|
||||
<entries />
|
||||
</TableToJsonHistory>
|
||||
<TableSortHistory>
|
||||
<entries />
|
||||
</TableSortHistory>
|
||||
</component>
|
||||
</project>
|
|
@ -1,65 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownProjectSettings" wasCopied="false">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true" replaceUnicodeEmoji="false" lastLayoutSetsDefault="false">
|
||||
<component name="FlexmarkProjectSettings">
|
||||
<FlexmarkHtmlSettings flexmarkSpecExampleRendering="0" flexmarkSpecExampleRenderHtml="false">
|
||||
<flexmarkSectionLanguages>
|
||||
<option name="1" value="Markdown" />
|
||||
<option name="2" value="HTML" />
|
||||
<option name="3" value="flexmark-ast:1" />
|
||||
</flexmarkSectionLanguages>
|
||||
</FlexmarkHtmlSettings>
|
||||
</component>
|
||||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" lastLayoutSetsDefault="false">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false" emojiShortcuts="1" emojiImages="0">
|
||||
<ParserSettings gitHubSyntaxChange="false" correctedInvalidSettings="false" emojiShortcuts="1" emojiImages="0">
|
||||
<PegdownExtensions>
|
||||
<option name="ABBREVIATIONS" value="false" />
|
||||
<option name="ANCHORLINKS" value="true" />
|
||||
<option name="ASIDE" value="false" />
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="AUTOLINKS" value="true" />
|
||||
<option name="DEFINITIONS" value="false" />
|
||||
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="FOOTNOTES" value="false" />
|
||||
<option name="HARDWRAPS" value="false" />
|
||||
<option name="HTML_DEEP_PARSER" value="false" />
|
||||
<option name="INSERTED" value="false" />
|
||||
<option name="QUOTES" value="false" />
|
||||
<option name="INTELLIJ_DUMMY_IDENTIFIER" value="true" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="SMARTS" value="false" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="SUBSCRIPT" value="false" />
|
||||
<option name="SUPERSCRIPT" value="false" />
|
||||
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
|
||||
<option name="SUPPRESS_INLINE_HTML" value="false" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
<option name="TOC" value="false" />
|
||||
<option name="WIKILINKS" value="true" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="ADMONITION_EXT" value="false" />
|
||||
<option name="ATTRIBUTES_EXT" value="false" />
|
||||
<option name="COMMONMARK_LISTS" value="true" />
|
||||
<option name="DUMMY" value="false" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="ENUMERATED_REFERENCES_EXT" value="false" />
|
||||
<option name="FLEXMARK_FRONT_MATTER" value="false" />
|
||||
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="GITBOOK_URL_ENCODING" value="false" />
|
||||
<option name="GITHUB_LISTS" value="false" />
|
||||
<option name="GITHUB_WIKI_LINKS" value="true" />
|
||||
<option name="GITLAB_EXT" value="false" />
|
||||
<option name="GITLAB_MATH_EXT" value="false" />
|
||||
<option name="GITLAB_MERMAID_EXT" value="false" />
|
||||
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
|
||||
<option name="JEKYLL_FRONT_MATTER" value="false" />
|
||||
<option name="MACROS_EXT" value="false" />
|
||||
<option name="NO_TEXT_ATTRIBUTES" value="false" />
|
||||
<option name="PARSE_HTML_ANCHOR_ID" value="false" />
|
||||
<option name="PRODUCTION_SPEC_PARSER" value="true" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false" imageUriSerials="false" addDocTypeHtml="true">
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="true" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
|
@ -68,15 +47,11 @@
|
|||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
<cssUriHistory />
|
||||
</CssSettings>
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
</project>
|
|
@ -1,3 +0,0 @@
|
|||
<component name="MarkdownNavigator.ProfileManager">
|
||||
<settings default="" pdf-export="" />
|
||||
</component>
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,3 +1,15 @@
|
|||
## 3.1.0
|
||||
|
||||
- Added `HeadlessInAppWebView` class to be able to use WebView in headless mode
|
||||
- Added `close`, `addMenuItem`, `addMenuItems` methods to `ChromeSafariBrowser`
|
||||
- Added `ChromeSafariBrowserMenuItem` class in order to create custom menu item for `ChromeSafariBrowser`.
|
||||
- Fixed `InAppWebView.channel` null when used by `InAppBrowserActivity` on android
|
||||
- Fixed iOS presentationStyle affecting only dismiss animation [#305](https://github.com/pichillilorenzo/flutter_inappwebview/issues/305)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Renamed `InAppWebViewWidgetOptions` to `InAppWebViewGroupOptions`.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
- Added `Promise` javascript [polyfill](https://github.com/tildeio/rsvp.js) for webviews that doesn't support it for `window.flutter_inappwebview.callHandler`
|
||||
|
|
149
README.md
149
README.md
|
@ -68,6 +68,7 @@ First, add `flutter_inappwebview` as a [dependency in your pubspec.yaml file](ht
|
|||
|
||||
Classes:
|
||||
- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated into the flutter widget tree. To use `InAppWebView` class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's `Info.plist` file, with the key `io.flutter.embedded_views_preview` and the value `YES`.
|
||||
- [HeadlessInAppWebView](#headlessinappwebview-class): Class that represents a WebView in headless mode. It can be used to run a WebView in background without attaching an `InAppWebView` to the widget tree.
|
||||
- [InAppBrowser](#inappbrowser-class): In-App Browser using native WebView.
|
||||
- [ChromeSafariBrowser](#chromesafaribrowser-class): In-App Browser using [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android / [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
|
||||
- [InAppLocalhostServer](#inapplocalhostserver-class): This class allows you to create a simple server on `http://localhost:[port]/`. The default `port` value is `8080`.
|
||||
|
@ -132,7 +133,7 @@ Future main() async {
|
|||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => new _MyAppState();
|
||||
}
|
||||
}z
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
|
@ -177,7 +178,7 @@ class _MyAppState extends State<MyApp> {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
)
|
||||
|
@ -280,7 +281,7 @@ Screenshots:
|
|||
* `addJavaScriptHandler({@required String handlerName, @required JavaScriptHandlerCallback callback})`: Adds a JavaScript message handler callback that listen to post messages sent from JavaScript by the handler with name `handlerName`.
|
||||
* `removeJavaScriptHandler({@required String handlerName})`: Removes a JavaScript message handler previously added with the `addJavaScriptHandler()` associated to `handlerName` key.
|
||||
* `takeScreenshot`: Takes a screenshot (in PNG format) of the WebView's visible viewport and returns a `Uint8List`. Returns `null` if it wasn't be able to take it.
|
||||
* `setOptions({@required InAppWebViewWidgetOptions options})`: Sets the WebView options with the new options and evaluates them.
|
||||
* `setOptions({@required InAppWebViewGroupOptions options})`: Sets the WebView options with the new options and evaluates them.
|
||||
* `getOptions`: Gets the current WebView options. Returns the options with `null` value if they are not set yet.
|
||||
* `getCopyBackForwardList`: Gets the `WebHistory` for this WebView. This contains the back/forward list for use in querying each item in the history stack.
|
||||
* `clearCache`: Clears all the webview's cache.
|
||||
|
@ -333,8 +334,8 @@ This event will be dispatched as soon as the platform (Android or iOS) is ready
|
|||
```
|
||||
|
||||
`window.flutter_inappwebview.callHandler` returns a JavaScript [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
|
||||
that can be used to get the json result returned by [JavaScriptHandlerCallback].
|
||||
In this case, simply return data that you want to send and it will be automatically json encoded using [jsonEncode] from the `dart:convert` library.
|
||||
that can be used to get the json result returned by `JavaScriptHandlerCallback.
|
||||
In this case, simply return data that you want to send and it will be automatically json encoded using `jsonEncode` from the `dart:convert` library.
|
||||
|
||||
So, on the JavaScript side, to get data coming from the Dart side, you will use:
|
||||
```html
|
||||
|
@ -498,6 +499,127 @@ Event names that starts with `android` or `ios` are events platform-specific.
|
|||
* `iosOnDidCommit`: Called when the web view begins to receive web content (available only on iOS).
|
||||
* `iosOnDidReceiveServerRedirectForProvisionalNavigation`: Called when a web view receives a server redirect (available only on iOS).
|
||||
|
||||
### `HeadlessInAppWebView` class
|
||||
|
||||
Class that represents a WebView in headless mode. It can be used to run a WebView in background without attaching an `InAppWebView` to the widget tree.
|
||||
|
||||
Remember to dispose it when you don't need it anymore.
|
||||
|
||||
As `InAppWebView`, it has the same options and events. Use `InAppWebViewController` to control the WebView instance.
|
||||
|
||||
Example:
|
||||
```dart
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
Future main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => new _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
HeadlessInAppWebView headlessWebView;
|
||||
String url = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
headlessWebView = new HeadlessInAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (controller) {
|
||||
print('HeadlessInAppWebView created!');
|
||||
},
|
||||
onConsoleMessage: (controller, consoleMessage) {
|
||||
print("CONSOLE MESSAGE: " + consoleMessage.message);
|
||||
},
|
||||
onLoadStart: (controller, url) async {
|
||||
print("onLoadStart $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
print("onLoadStop $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) {
|
||||
print("onUpdateVisitedHistory $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
headlessWebView.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"HeadlessInAppWebView",
|
||||
)),
|
||||
drawer: myDrawer(context: context),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
child: Text(
|
||||
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
|
||||
),
|
||||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
await headlessWebView.dispose();
|
||||
await headlessWebView.run();
|
||||
},
|
||||
child: Text("Run HeadlessInAppWebView")),
|
||||
),
|
||||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await headlessWebView.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
|
||||
} on MissingPluginException catch(e) {
|
||||
print("HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!");
|
||||
}
|
||||
},
|
||||
child: Text("Send console.log message")),
|
||||
),
|
||||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
headlessWebView.dispose();
|
||||
},
|
||||
child: Text("Dispose HeadlessInAppWebView")),
|
||||
)
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `InAppBrowser` class
|
||||
|
||||
In-App Browser using native WebView.
|
||||
|
@ -596,7 +718,7 @@ class _MyAppState extends State<MyApp> {
|
|||
widget.browser.openFile(
|
||||
assetFilePath: "assets/index.html",
|
||||
options: InAppBrowserClassOptions(
|
||||
inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
|
||||
inAppWebViewGroupOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
useShouldOverrideUrlLoading: true,
|
||||
useOnLoadResource: true,
|
||||
|
@ -744,6 +866,16 @@ class _MyAppState extends State<MyApp> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
widget.browser.addMenuItem(new ChromeSafariBrowserMenuItem(id: 1, label: 'Custom item menu 1', action: (url, title) {
|
||||
print('Custom item menu 1 clicked!');
|
||||
print(url);
|
||||
print(title);
|
||||
}));
|
||||
widget.browser.addMenuItem(new ChromeSafariBrowserMenuItem(id: 2, label: 'Custom item menu 2', action: (url, title) {
|
||||
print('Custom item menu 2 clicked!');
|
||||
print(url);
|
||||
print(title);
|
||||
}));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -785,6 +917,9 @@ Screenshots:
|
|||
|
||||
* `open({@required String url, ChromeSafariBrowserClassOptions options, Map<String, String> headersFallback = const {}, InAppBrowserClassOptions optionsFallback})`: Opens an `url` in a new `ChromeSafariBrowser` instance.
|
||||
* `isOpened`: Returns `true` if the `ChromeSafariBrowser` instance is opened, otherwise `false`.
|
||||
* `close`: Closes the `ChromeSafariBrowser` instance.
|
||||
* `addMenuItem`: Adds a `ChromeSafariBrowserMenuItem` to the menu.
|
||||
* `addMenuItems`: Adds a list of `ChromeSafariBrowserMenuItem` to the menu.
|
||||
|
||||
#### `ChromeSafariBrowser` options
|
||||
|
||||
|
@ -846,7 +981,7 @@ Future main() async {
|
|||
child: InAppWebView(
|
||||
initialUrl: "http://localhost:8080/assets/index.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
inAppWebViewOptions: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
)
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.pichillilorenzo.flutter_inappwebview">
|
||||
<application>
|
||||
<activity android:theme="@style/AppTheme" android:name="com.pichillilorenzo.flutter_inappwebview.InAppBrowserActivity" android:configChanges="orientation|screenSize"></activity>
|
||||
<activity android:theme="@style/AppTheme" android:name="com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity" android:configChanges="orientation|screenSize"></activity>
|
||||
<activity android:theme="@style/ThemeTransparent" android:name="com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ChromeCustomTabsActivity" android:configChanges="orientation|screenSize"></activity>
|
||||
<receiver android:name="com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ActionBroadcastReceiver" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,39 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class ActionBroadcastReceiver extends BroadcastReceiver {
|
||||
protected static final String LOG_TAG = "ActionBroadcastReceiver";
|
||||
public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID";
|
||||
public static final String KEY_ACTION_UUID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_UUID";
|
||||
public static final String KEY_URL_TITLE = "android.intent.extra.SUBJECT";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String url = intent.getDataString();
|
||||
if (url != null) {
|
||||
Bundle b = intent.getExtras();
|
||||
String uuid = b.getString(KEY_ACTION_UUID);
|
||||
int id = b.getInt(KEY_ACTION_ID);
|
||||
String title = b.getString(KEY_URL_TITLE);
|
||||
|
||||
MethodChannel channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + uuid);
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("url", url);
|
||||
obj.put("title", title);
|
||||
obj.put("id", id);
|
||||
channel.invokeMethod("onChromeSafariBrowserMenuItemActionPerform", obj);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,24 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.browser.customtabs.CustomTabsCallback;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.browser.customtabs.CustomTabsService;
|
||||
import androidx.browser.customtabs.CustomTabsSession;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
|
@ -52,6 +55,8 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
|||
options = new ChromeCustomTabsOptions();
|
||||
options.parse((HashMap<String, Object>) b.getSerializable("options"));
|
||||
|
||||
final List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) b.getSerializable("menuItemList");
|
||||
|
||||
final ChromeCustomTabsActivity chromeCustomTabsActivity = this;
|
||||
|
||||
customTabActivityHelper = new CustomTabActivityHelper();
|
||||
|
@ -63,18 +68,17 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
|||
customTabActivityHelper.mayLaunchUrl(uri, null, null);
|
||||
|
||||
builder = new CustomTabsIntent.Builder(customTabsSession);
|
||||
prepareCustomTabs(menuItemList);
|
||||
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
prepareCustomTabs(customTabsIntent);
|
||||
prepareCustomTabsIntent(customTabsIntent);
|
||||
|
||||
CustomTabActivityHelper.openCustomTab(chromeCustomTabsActivity, customTabsIntent, uri, CHROME_CUSTOM_TAB_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomTabsDisconnected() {
|
||||
customTabsSession = null;
|
||||
finish();
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("uuid", uuid);
|
||||
channel.invokeMethod("onChromeSafariBrowserClosed", obj);
|
||||
chromeCustomTabsActivity.close();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -122,12 +126,23 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
|||
@Override
|
||||
public void onMethodCall(final MethodCall call, final MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
case "close":
|
||||
this.onStop();
|
||||
this.onDestroy();
|
||||
this.close();
|
||||
|
||||
// https://stackoverflow.com/a/41596629/4637638
|
||||
Intent myIntent = new Intent(Shared.activity, Shared.activity.getClass());
|
||||
myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
myIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
Shared.activity.startActivity(myIntent);
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareCustomTabs(CustomTabsIntent customTabsIntent) {
|
||||
private void prepareCustomTabs(List<HashMap<String, Object>> menuItemList) {
|
||||
if (options.addDefaultShareMenuItem)
|
||||
builder.addDefaultShareMenuItem();
|
||||
|
||||
|
@ -141,6 +156,14 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
|||
|
||||
builder.setInstantAppsEnabled(options.instantAppsEnabled);
|
||||
|
||||
for (HashMap<String, Object> menuItem : menuItemList) {
|
||||
int id = (int) menuItem.get("id");
|
||||
String label = (String) menuItem.get("label");
|
||||
builder.addMenuItem(label, createPendingIntent(id));
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareCustomTabsIntent(CustomTabsIntent customTabsIntent) {
|
||||
if (options.packageName != null)
|
||||
customTabsIntent.intent.setPackage(options.packageName);
|
||||
else
|
||||
|
@ -165,12 +188,27 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
|||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == CHROME_CUSTOM_TAB_REQUEST_CODE) {
|
||||
customTabsSession = null;
|
||||
finish();
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("uuid", uuid);
|
||||
InAppWebViewFlutterPlugin.inAppBrowserManager.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
customTabsSession = null;
|
||||
finish();
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("uuid", uuid);
|
||||
channel.invokeMethod("onChromeSafariBrowserClosed", obj);
|
||||
}
|
||||
|
||||
private PendingIntent createPendingIntent(int actionSourceId) {
|
||||
Intent actionIntent = new Intent(this, ActionBroadcastReceiver.class);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putInt(ActionBroadcastReceiver.KEY_ACTION_ID, actionSourceId);
|
||||
extras.putString(ActionBroadcastReceiver.KEY_ACTION_UUID, uuid);
|
||||
actionIntent.putExtras(extras);
|
||||
|
||||
return PendingIntent.getBroadcast(
|
||||
this, actionSourceId, actionIntent, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,12 @@ import android.util.Log;
|
|||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ChromeCustomTabsActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.CustomTabActivityHelper;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserOptions;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
|
@ -40,7 +43,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
String uuidFallback = (String) call.argument("uuidFallback");
|
||||
Map<String, String> headersFallback = (Map<String, String>) call.argument("headersFallback");
|
||||
HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
|
||||
open(activity, uuid, url, options, uuidFallback, headersFallback, optionsFallback, result);
|
||||
List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList");
|
||||
open(activity, uuid, url, options, uuidFallback, headersFallback, optionsFallback, menuItemList, result);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -48,7 +52,8 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
}
|
||||
}
|
||||
|
||||
public void open(Activity activity, String uuid, String url, HashMap<String, Object> options, String uuidFallback, Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, MethodChannel.Result result) {
|
||||
public void open(Activity activity, String uuid, String url, HashMap<String, Object> options, String uuidFallback,
|
||||
Map<String, String> headersFallback, HashMap<String, Object> optionsFallback, List<HashMap<String, Object>> menuItemList, MethodChannel.Result result) {
|
||||
|
||||
Intent intent = null;
|
||||
Bundle extras = new Bundle();
|
||||
|
@ -58,6 +63,7 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
extras.putString("uuid", uuid);
|
||||
extras.putSerializable("options", options);
|
||||
extras.putSerializable("headers", (Serializable) headersFallback);
|
||||
extras.putSerializable("menuItemList", (Serializable) menuItemList);
|
||||
|
||||
if (CustomTabActivityHelper.isAvailable(activity)) {
|
||||
intent = new Intent(activity, ChromeCustomTabsActivity.class);
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.FlutterWebView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugin.common.MethodChannel.Result;
|
||||
|
||||
/**
|
||||
* InAppBrowserManager
|
||||
*/
|
||||
public class HeadlessInAppWebViewManager implements MethodChannel.MethodCallHandler {
|
||||
|
||||
public MethodChannel channel;
|
||||
protected static final String LOG_TAG = "HeadlessInAppWebViewManager";
|
||||
Map<String, FlutterWebView> flutterWebViews = new HashMap<>();
|
||||
|
||||
public HeadlessInAppWebViewManager(BinaryMessenger messenger) {
|
||||
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_headless_inappwebview");
|
||||
channel.setMethodCallHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(final MethodCall call, final Result result) {
|
||||
final Activity activity = Shared.activity;
|
||||
final String uuid = (String) call.argument("uuid");
|
||||
|
||||
switch (call.method) {
|
||||
case "createHeadlessWebView":
|
||||
{
|
||||
HashMap<String, Object> params = (HashMap<String, Object>) call.argument("params");
|
||||
createHeadlessWebView(activity, uuid, params);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
case "disposeHeadlessWebView":
|
||||
disposeHeadlessWebView(uuid);
|
||||
result.success(true);
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void createHeadlessWebView(Activity activity, String uuid, HashMap<String, Object> params) {
|
||||
FlutterWebView flutterWebView = new FlutterWebView(Shared.messenger, activity, uuid, params, null);
|
||||
flutterWebViews.put(uuid, flutterWebView);
|
||||
}
|
||||
|
||||
public void disposeHeadlessWebView(String uuid) {
|
||||
if (flutterWebViews.containsKey(uuid)) {
|
||||
flutterWebViews.get(uuid).dispose();
|
||||
flutterWebViews.remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
channel.setMethodCallHandler(null);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
package com.pichillilorenzo.flutter_inappwebview.InAppBrowser;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -26,6 +26,8 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewOptions;
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -65,6 +67,7 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
|
||||
webView = findViewById(R.id.webView);
|
||||
webView.inAppBrowserActivity = this;
|
||||
webView.channel = channel;
|
||||
|
||||
fromActivity = b.getString("fromActivity");
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
package com.pichillilorenzo.flutter_inappwebview.InAppBrowser;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Options;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
|
@ -32,6 +32,8 @@ import android.os.Bundle;
|
|||
import android.webkit.MimeTypeMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
@ -14,6 +14,8 @@ import android.webkit.WebViewClient;
|
|||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.DisplayListenerProxy;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewOptions;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -37,7 +39,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
public InAppWebView webView;
|
||||
public final MethodChannel channel;
|
||||
|
||||
public FlutterWebView(BinaryMessenger messenger, final Context context, int id, HashMap<String, Object> params, View containerView) {
|
||||
public FlutterWebView(BinaryMessenger messenger, final Context context, Object id, HashMap<String, Object> params, View containerView) {
|
||||
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_" + id);
|
||||
channel.setMethodCallHandler(this);
|
||||
|
||||
|
@ -93,6 +95,12 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
}
|
||||
else
|
||||
webView.loadUrl(initialUrl, initialHeaders);
|
||||
|
||||
if (containerView == null && id instanceof String) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("uuid", id);
|
||||
channel.invokeMethod("onHeadlessWebViewCreated", obj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,12 +1,13 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.FlutterWebView;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.PluginRegistry.Registrar;
|
||||
import io.flutter.plugin.common.StandardMessageCodec;
|
||||
import io.flutter.plugin.platform.PlatformView;
|
||||
import io.flutter.plugin.platform.PlatformViewFactory;
|
|
@ -5,19 +5,16 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintDocumentAdapter;
|
||||
import android.print.PrintManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.DownloadListener;
|
||||
import android.webkit.ValueCallback;
|
||||
|
@ -27,17 +24,12 @@ import android.webkit.WebSettings;
|
|||
import android.webkit.WebStorage;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
|
||||
import android.view.ActionMode;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerHandler;
|
||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerTrigger;
|
||||
import com.pichillilorenzo.flutter_inappwebview.FlutterWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
@ -62,7 +54,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public InAppBrowserActivity inAppBrowserActivity;
|
||||
public FlutterWebView flutterWebView;
|
||||
public MethodChannel channel;
|
||||
public int id;
|
||||
public Object id;
|
||||
public InAppWebViewClient inAppWebViewClient;
|
||||
public InAppWebViewChromeClient inAppWebViewChromeClient;
|
||||
public InAppWebViewOptions options;
|
||||
|
@ -527,7 +519,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
super(context, attrs, defaultStyle);
|
||||
}
|
||||
|
||||
public InAppWebView(Context context, Object obj, int id, InAppWebViewOptions options, View containerView) {
|
||||
public InAppWebView(Context context, Object obj, Object id, InAppWebViewOptions options, View containerView) {
|
||||
super(context, containerView);
|
||||
if (obj instanceof InAppBrowserActivity)
|
||||
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
|
||||
|
@ -891,7 +883,8 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
|
||||
public void takeScreenshot(final MethodChannel.Result result) {
|
||||
post(new Runnable() {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int height = (int) (getContentHeight() * scale + 0.5);
|
||||
|
@ -1199,7 +1192,8 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
scriptToInject = String.format(jsWrapper, jsonSourceString);
|
||||
}
|
||||
final String finalScriptToInject = scriptToInject;
|
||||
post(new Runnable() {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
|
|
|
@ -27,8 +27,7 @@ import android.widget.LinearLayout;
|
|||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.FlutterWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
|
|
|
@ -24,9 +24,7 @@ import androidx.annotation.RequiresApi;
|
|||
|
||||
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.Credential;
|
||||
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.CredentialDatabase;
|
||||
import com.pichillilorenzo.flutter_inappwebview.FlutterWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.FlutterWebViewFactory;
|
||||
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
|
@ -19,6 +21,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
|||
protected static final String LOG_TAG = "InAppWebViewFlutterPL";
|
||||
|
||||
public static InAppBrowserManager inAppBrowserManager;
|
||||
public static HeadlessInAppWebViewManager headlessInAppWebViewManager;
|
||||
public static ChromeSafariBrowserManager chromeSafariBrowserManager;
|
||||
public static InAppWebViewStatic inAppWebViewStatic;
|
||||
public static MyCookieManager myCookieManager;
|
||||
|
@ -49,6 +52,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
|||
Shared.messenger = messenger;
|
||||
|
||||
inAppBrowserManager = new InAppBrowserManager(messenger);
|
||||
headlessInAppWebViewManager = new HeadlessInAppWebViewManager(messenger);
|
||||
chromeSafariBrowserManager = new ChromeSafariBrowserManager(messenger);
|
||||
|
||||
platformViewRegistry.registerViewFactory(
|
||||
|
@ -67,6 +71,10 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
|||
inAppBrowserManager.dispose();
|
||||
inAppBrowserManager = null;
|
||||
}
|
||||
if (headlessInAppWebViewManager != null) {
|
||||
headlessInAppWebViewManager.dispose();
|
||||
headlessInAppWebViewManager = null;
|
||||
}
|
||||
if (chromeSafariBrowserManager != null) {
|
||||
chromeSafariBrowserManager.dispose();
|
||||
chromeSafariBrowserManager = null;
|
||||
|
|
|
@ -7,6 +7,8 @@ import android.util.Log;
|
|||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.FlutterWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
tools:context=".InAppBrowserActivity"
|
||||
tools:context=".InAppBrowser.InAppBrowserActivity"
|
||||
android:focusable="true">
|
||||
|
||||
<com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:appcompat="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".InAppBrowserActivity">
|
||||
tools:context=".InAppBrowser.InAppBrowserActivity">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_go_back"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"android":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_macos-0.1.0+3/","dependencies":[]},{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos"]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-09 04:59:17.693618","version":"1.17.0"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"android":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_macos-0.1.0+3/","dependencies":[]},{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos"]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-11 02:42:13.697935","version":"1.17.0"}
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/sh
|
||||
# This is a generated file; do not edit or check into version control.
|
||||
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
|
||||
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
|
||||
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
|
||||
export "FLUTTER_BUILD_DIR=build"
|
||||
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
||||
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
|
||||
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
|
||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||
export "FLUTTER_BUILD_NUMBER=1"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
|
@ -35,6 +35,16 @@ class _ChromeSafariBrowserExampleScreenState
|
|||
extends State<ChromeSafariBrowserExampleScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
widget.browser.addMenuItem(new ChromeSafariBrowserMenuItem(id: 1, label: 'Custom item menu 1', action: (url, title) {
|
||||
print('Custom item menu 1 clicked!');
|
||||
print(url);
|
||||
print(title);
|
||||
}));
|
||||
widget.browser.addMenuItem(new ChromeSafariBrowserMenuItem(id: 2, label: 'Custom item menu 2', action: (url, title) {
|
||||
print('Custom item menu 2 clicked!');
|
||||
print(url);
|
||||
print(title);
|
||||
}));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -53,7 +63,10 @@ class _ChromeSafariBrowserExampleScreenState
|
|||
url: "https://flutter.dev/",
|
||||
options: ChromeSafariBrowserClassOptions(
|
||||
android: AndroidChromeCustomTabsOptions(addDefaultShareMenuItem: false, keepAliveEnabled: true),
|
||||
ios: IOSSafariOptions(barCollapsingEnabled: true)));
|
||||
ios: IOSSafariOptions(
|
||||
dismissButtonStyle: IOSSafariDismissButtonStyle.CLOSE,
|
||||
presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN
|
||||
)));
|
||||
},
|
||||
child: Text("Open Chrome Safari Browser")),
|
||||
));
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'main.dart';
|
||||
|
||||
class HeadlessInAppWebViewExampleScreen extends StatefulWidget {
|
||||
@override
|
||||
_HeadlessInAppWebViewExampleScreenState createState() =>
|
||||
new _HeadlessInAppWebViewExampleScreenState();
|
||||
}
|
||||
|
||||
class _HeadlessInAppWebViewExampleScreenState extends State<HeadlessInAppWebViewExampleScreen> {
|
||||
HeadlessInAppWebView headlessWebView;
|
||||
String url = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
headlessWebView = new HeadlessInAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (controller) {
|
||||
print('HeadlessInAppWebView created!');
|
||||
},
|
||||
onConsoleMessage: (controller, consoleMessage) {
|
||||
print("CONSOLE MESSAGE: " + consoleMessage.message);
|
||||
},
|
||||
onLoadStart: (controller, url) async {
|
||||
print("onLoadStart $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
print("onLoadStop $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) {
|
||||
print("onUpdateVisitedHistory $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
headlessWebView.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"HeadlessInAppWebView",
|
||||
)),
|
||||
drawer: myDrawer(context: context),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
child: Text(
|
||||
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
|
||||
),
|
||||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
await headlessWebView.dispose();
|
||||
await headlessWebView.run();
|
||||
},
|
||||
child: Text("Run HeadlessInAppWebView")),
|
||||
),
|
||||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await headlessWebView.webViewController.evaluateJavascript(source: """console.log('Here is the message!');""");
|
||||
} on MissingPluginException catch(e) {
|
||||
print("HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!");
|
||||
}
|
||||
},
|
||||
child: Text("Send console.log message")),
|
||||
),
|
||||
Center(
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
headlessWebView.dispose();
|
||||
},
|
||||
child: Text("Dispose HeadlessInAppWebView")),
|
||||
)
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -90,7 +90,7 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
|
|||
await widget.browser.openFile(
|
||||
assetFilePath: "assets/index.html",
|
||||
options: InAppBrowserClassOptions(
|
||||
inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
|
||||
inAppWebViewGroupOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
useShouldOverrideUrlLoading: true,
|
||||
|
|
|
@ -52,7 +52,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
initialUrl: "https://flutter.dev/",
|
||||
// initialFile: "assets/index.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
debuggingEnabled: true,
|
||||
),
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'dart:async';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:flutter_inappwebview_example/chrome_safari_browser_example.screen.dart';
|
||||
import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart';
|
||||
import 'package:flutter_inappwebview_example/in_app_webiew_example.screen.dart';
|
||||
import 'package:flutter_inappwebview_example/in_app_browser_example.screen.dart';
|
||||
|
||||
|
@ -44,6 +44,12 @@ Drawer myDrawer({@required BuildContext context}) {
|
|||
Navigator.pushReplacementNamed(context, '/');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('HeadlessInAppWebView'),
|
||||
onTap: () {
|
||||
Navigator.pushReplacementNamed(context, '/HeadlessInAppWebView');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -74,6 +80,7 @@ class _MyAppState extends State<MyApp> {
|
|||
'/': (context) => InAppWebViewExampleScreen(),
|
||||
'/InAppBrowser': (context) => InAppBrowserExampleScreen(),
|
||||
'/ChromeSafariBrowser': (context) => ChromeSafariBrowserExampleScreen(),
|
||||
'/HeadlessInAppWebView': (context) => HeadlessInAppWebViewExampleScreen(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ class InAppWebViewAjaxTestState extends WidgetTestState {
|
|||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -29,7 +29,7 @@ class InAppWebViewContentBlockerTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -30,7 +30,7 @@ class InAppWebViewCookieManagerTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -74,7 +74,7 @@ class InAppWebViewFetchTestState extends WidgetTestState {
|
|||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -37,7 +37,7 @@ class InAppWebViewHttpAuthCredentialDatabaseTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -65,7 +65,7 @@ class InAppWebViewInitialDataTestState extends WidgetTestState {
|
|||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -28,7 +28,7 @@ class InAppWebViewInitialFileTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_initial_file_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -29,7 +29,7 @@ class InAppWebViewInitialUrlTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -43,7 +43,7 @@ class InAppWebViewJavaScriptHandlerTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_javascript_handler_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -28,7 +28,7 @@ class InAppWebViewOnConsoleMessageTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_console_message_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -28,7 +28,7 @@ class InAppWebViewOnCreateWindowTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_create_window_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -48,7 +48,7 @@ class InAppWebViewOnDownloadStartTestState extends WidgetTestState {
|
|||
</html>
|
||||
"""),
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -28,7 +28,7 @@ class InAppWebViewOnFindResultReceivedTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_initial_file_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -36,7 +36,7 @@ class InAppWebViewOnJsDialogTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_js_dialog_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -29,7 +29,7 @@ class InAppWebViewOnLoadErrorTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://not-existing-domain.org/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -29,7 +29,7 @@ class InAppWebViewOnLoadHttpErrorTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://google.com/404",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -29,7 +29,7 @@ class InAppWebViewOnLoadResourceCustomSchemeTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_load_resource_custom_scheme_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -34,7 +34,7 @@ class InAppWebViewOnLoadResourceTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_on_load_resource_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -28,7 +28,7 @@ class InAppWebViewOnNavigationStateChangeTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -29,7 +29,7 @@ class InAppWebViewOnProgressChangedTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -30,7 +30,7 @@ class InAppWebViewOnReceivedHttpAuthRequestTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -31,7 +31,7 @@ class InAppWebViewOnSafeBrowsingHitTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: (Platform.isAndroid) ? "chrome://safe-browsing/match?type=malware" : "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
// if I set javaScriptEnabled to true, it will crash!
|
||||
javaScriptEnabled: false,
|
||||
|
|
|
@ -30,7 +30,7 @@ class InAppWebViewOnScrollChangedTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://flutter.dev/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -28,7 +28,7 @@ class InAppWebViewShouldOverrideUrlLoadingTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialFile: "test_assets/in_app_webview_initial_file_test.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true,
|
||||
|
|
|
@ -30,7 +30,7 @@ class InAppWebViewSslRequestTestState extends WidgetTestState {
|
|||
child: InAppWebView(
|
||||
initialUrl: "https://${environment["NODE_SERVER_IP"]}:4433/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
debuggingEnabled: true
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/ios/Flutter/App.framework/flutter_assets/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.pub" />
|
||||
|
|
|
@ -41,7 +41,8 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
let uuidFallback: String = arguments!["uuidFallback"] as! String
|
||||
let headersFallback = arguments!["headersFallback"] as! [String: String]
|
||||
let optionsFallback = arguments!["optionsFallback"] as! [String: Any?]
|
||||
open(uuid: uuid, url: url, options: options, uuidFallback: uuidFallback, headersFallback: headersFallback, optionsFallback: optionsFallback, result: result)
|
||||
let menuItemList = arguments!["menuItemList"] as! [[String: Any]]
|
||||
open(uuid: uuid, url: url, options: options, uuidFallback: uuidFallback, headersFallback: headersFallback, optionsFallback: optionsFallback, menuItemList: menuItemList, result: result)
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
|
@ -49,7 +50,7 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
public func open(uuid: String, url: String, options: [String: Any?], uuidFallback: String?, headersFallback: [String: String], optionsFallback: [String: Any?], result: @escaping FlutterResult) {
|
||||
public func open(uuid: String, url: String, options: [String: Any?], uuidFallback: String?, headersFallback: [String: String], optionsFallback: [String: Any?], menuItemList: [[String: Any]], result: @escaping FlutterResult) {
|
||||
let absoluteUrl = URL(string: url)!.absoluteURL
|
||||
|
||||
if self.previousStatusBarStyle == -1 {
|
||||
|
@ -85,10 +86,12 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
|
|||
}
|
||||
|
||||
safari.uuid = uuid
|
||||
safari.menuItemList = menuItemList
|
||||
safari.prepareMethodChannel()
|
||||
safari.delegate = safari
|
||||
safari.tmpWindow = tmpWindow
|
||||
safari.safariOptions = safariOptions
|
||||
safari.prepareSafariBrowser()
|
||||
|
||||
tmpController.present(safari, animated: true) {
|
||||
result(true)
|
||||
|
|
|
@ -12,22 +12,27 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
|
|||
|
||||
private weak var registrar: FlutterPluginRegistrar?
|
||||
var webView: InAppWebView?
|
||||
var viewId: Int64 = 0
|
||||
var viewId: Any = 0
|
||||
var channel: FlutterMethodChannel?
|
||||
var myView: UIView?
|
||||
|
||||
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: NSDictionary) {
|
||||
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Any, arguments args: NSDictionary) {
|
||||
super.init()
|
||||
|
||||
self.registrar = registrar
|
||||
self.viewId = viewId
|
||||
|
||||
myView = UIView(frame: frame)
|
||||
|
||||
let channelName = "com.pichillilorenzo/flutter_inappwebview_" + String(viewId)
|
||||
var channelName = ""
|
||||
if let id = viewId as? Int64 {
|
||||
channelName = "com.pichillilorenzo/flutter_inappwebview_" + String(id)
|
||||
} else if let id = viewId as? String {
|
||||
channelName = "com.pichillilorenzo/flutter_inappwebview_" + id
|
||||
}
|
||||
channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger())
|
||||
channel!.setMethodCallHandler(LeakAvoider(delegate: self).handle)
|
||||
|
||||
myView = UIView(frame: frame)
|
||||
|
||||
let initialUrl = args["initialUrl"] as? String
|
||||
let initialFile = args["initialFile"] as? String
|
||||
let initialData = args["initialData"] as? [String: String]
|
||||
|
@ -74,6 +79,20 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
|
|||
}
|
||||
}
|
||||
load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
|
||||
|
||||
if (frame.isEmpty && viewId is String) {
|
||||
/// Note: The WKWebView behaves very unreliable when rendering offscreen
|
||||
/// on a device. This is especially true with JavaScript, which simply
|
||||
/// won't be executed sometimes.
|
||||
/// Therefore, I decided to add this very ugly hack where the rendering
|
||||
/// webview will be added to the view hierarchy (between the
|
||||
/// rootViewController's view and the key window).
|
||||
self.myView!.alpha = 0.01
|
||||
UIApplication.shared.keyWindow!.insertSubview(self.myView!, at: 0)
|
||||
|
||||
let arguments: [String: Any] = ["uuid": viewId]
|
||||
channel!.invokeMethod("onHeadlessWebViewCreated", arguments: arguments)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// HeadlessInAppWebViewManager.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 10/05/2020.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import Flutter
|
||||
import UIKit
|
||||
import WebKit
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
|
||||
public class HeadlessInAppWebViewManager: NSObject, FlutterPlugin {
|
||||
static var registrar: FlutterPluginRegistrar?
|
||||
static var channel: FlutterMethodChannel?
|
||||
var flutterWebViews: [String: FlutterWebViewController] = [:]
|
||||
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
|
||||
}
|
||||
|
||||
init(registrar: FlutterPluginRegistrar) {
|
||||
super.init()
|
||||
HeadlessInAppWebViewManager.registrar = registrar
|
||||
HeadlessInAppWebViewManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_headless_inappwebview", binaryMessenger: registrar.messenger())
|
||||
registrar.addMethodCallDelegate(self, channel: HeadlessInAppWebViewManager.channel!)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
let arguments = call.arguments as? NSDictionary
|
||||
let uuid: String = arguments!["uuid"] as! String
|
||||
|
||||
switch call.method {
|
||||
case "createHeadlessWebView":
|
||||
let params = arguments!["params"] as! [String: Any?]
|
||||
createHeadlessWebView(uuid: uuid, params: params)
|
||||
result(true)
|
||||
break
|
||||
case "disposeHeadlessWebView":
|
||||
disposeHeadlessWebView(uuid: uuid)
|
||||
result(true)
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func createHeadlessWebView(uuid: String, params: [String: Any?]) {
|
||||
let controller = FlutterWebViewController(registrar: HeadlessInAppWebViewManager.registrar!,
|
||||
withFrame: CGRect.zero,
|
||||
viewIdentifier: uuid,
|
||||
arguments: params as NSDictionary)
|
||||
flutterWebViews[uuid] = controller
|
||||
}
|
||||
|
||||
public func disposeHeadlessWebView(uuid: String) {
|
||||
if let _ = flutterWebViews[uuid] {
|
||||
flutterWebViews.removeValue(forKey: uuid)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
|
|||
var tmpWindow: UIWindow?
|
||||
var safariOptions: SafariBrowserOptions?
|
||||
var uuid: String = ""
|
||||
var menuItemList: [[String: Any]] = []
|
||||
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
|
||||
|
@ -30,11 +31,20 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
|
|||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
|
||||
let arguments = call.arguments as? NSDictionary
|
||||
|
||||
switch call.method {
|
||||
case "close":
|
||||
close()
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public override func viewWillAppear(_ animated: Bool) {
|
||||
prepareSafariBrowser()
|
||||
// prepareSafariBrowser()
|
||||
super.viewWillAppear(animated)
|
||||
onChromeSafariBrowserOpened()
|
||||
}
|
||||
|
@ -83,23 +93,25 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
|
|||
}
|
||||
|
||||
public func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
|
||||
// print("activityItemsFor")
|
||||
// print(URL)
|
||||
// print(title)
|
||||
return []
|
||||
var uiActivities: [UIActivity] = []
|
||||
menuItemList.forEach { (menuItem) in
|
||||
let activity = CustomUIActivity(uuid: uuid, id: menuItem["id"] as! Int64, url: URL, title: title, label: menuItem["label"] as? String, type: nil, image: nil)
|
||||
uiActivities.append(activity)
|
||||
}
|
||||
return uiActivities
|
||||
}
|
||||
|
||||
public func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivity.ActivityType] {
|
||||
//
|
||||
// public func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivity.ActivityType] {
|
||||
// print("excludedActivityTypesFor")
|
||||
// print(URL)
|
||||
// print(title)
|
||||
return []
|
||||
}
|
||||
|
||||
public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {
|
||||
// return []
|
||||
// }
|
||||
//
|
||||
// public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {
|
||||
// print("initialLoadDidRedirectTo")
|
||||
// print(URL)
|
||||
}
|
||||
// }
|
||||
|
||||
public func onChromeSafariBrowserOpened() {
|
||||
channel!.invokeMethod("onChromeSafariBrowserOpened", arguments: [])
|
||||
|
@ -146,3 +158,54 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
|
|||
return hexInt
|
||||
}
|
||||
}
|
||||
|
||||
class CustomUIActivity : UIActivity {
|
||||
var uuid: String
|
||||
var id: Int64
|
||||
var url: URL
|
||||
var title: String?
|
||||
var type: UIActivity.ActivityType?
|
||||
var label: String?
|
||||
var image: UIImage?
|
||||
|
||||
init(uuid: String, id: Int64, url: URL, title: String?, label: String?, type: UIActivity.ActivityType?, image: UIImage?) {
|
||||
self.uuid = uuid
|
||||
self.id = id
|
||||
self.url = url
|
||||
self.title = title
|
||||
self.label = label
|
||||
self.type = type
|
||||
self.image = image
|
||||
}
|
||||
|
||||
override class var activityCategory: UIActivity.Category {
|
||||
return .action
|
||||
}
|
||||
|
||||
override var activityType: UIActivity.ActivityType? {
|
||||
return type
|
||||
}
|
||||
|
||||
override var activityTitle: String? {
|
||||
return label
|
||||
}
|
||||
|
||||
override var activityImage: UIImage? {
|
||||
return image
|
||||
}
|
||||
|
||||
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func perform() {
|
||||
let channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser_" + uuid, binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
|
||||
|
||||
let arguments: [String: Any?] = [
|
||||
"url": url.absoluteString,
|
||||
"title": title,
|
||||
"id": id,
|
||||
]
|
||||
channel.invokeMethod("onChromeSafariBrowserMenuItemActionPerform", arguments: arguments)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
var myWebStorageManager: Any?
|
||||
var credentialDatabase: CredentialDatabase?
|
||||
var inAppBrowserManager: InAppBrowserManager?
|
||||
var headlessInAppWebViewManager: HeadlessInAppWebViewManager?
|
||||
var chromeSafariBrowserManager: ChromeSafariBrowserManager?
|
||||
|
||||
var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
|
||||
|
@ -46,6 +47,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: "com.pichillilorenzo/flutter_inappwebview")
|
||||
|
||||
inAppBrowserManager = InAppBrowserManager(registrar: registrar)
|
||||
headlessInAppWebViewManager = HeadlessInAppWebViewManager(registrar: registrar)
|
||||
chromeSafariBrowserManager = ChromeSafariBrowserManager(registrar: registrar)
|
||||
inAppWebViewStatic = InAppWebViewStatic(registrar: registrar)
|
||||
if #available(iOS 11.0, *) {
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
library flutter_inappwebview;
|
||||
|
||||
export 'src/types.dart';
|
||||
export 'src/webview.dart';
|
||||
export 'src/in_app_webview_controller.dart';
|
||||
export 'src/headless_in_app_webview.dart';
|
||||
export 'src/in_app_webview.dart';
|
||||
export 'src/in_app_browser.dart';
|
||||
export 'src/cookie_manager.dart';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -7,8 +7,6 @@ import 'package:flutter/services.dart';
|
|||
import 'types.dart';
|
||||
import 'in_app_browser.dart';
|
||||
|
||||
///ChromeSafariBrowser class.
|
||||
///
|
||||
///This class uses native [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android
|
||||
///and [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
|
||||
///
|
||||
|
@ -16,6 +14,7 @@ import 'in_app_browser.dart';
|
|||
class ChromeSafariBrowser {
|
||||
String uuid;
|
||||
InAppBrowser browserFallback;
|
||||
Map<int, ChromeSafariBrowserMenuItem> _menuItems = new HashMap();
|
||||
bool _isOpened = false;
|
||||
MethodChannel _channel;
|
||||
static const MethodChannel _sharedChannel = const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser');
|
||||
|
@ -42,6 +41,12 @@ class ChromeSafariBrowser {
|
|||
onClosed();
|
||||
this._isOpened = false;
|
||||
break;
|
||||
case "onChromeSafariBrowserMenuItemActionPerform":
|
||||
String url = call.arguments["url"];
|
||||
String title = call.arguments["title"];
|
||||
int id = call.arguments["id"].toInt();
|
||||
this._menuItems[id].action(url, title);
|
||||
break;
|
||||
default:
|
||||
throw UnimplementedError("Unimplemented ${call.method} method");
|
||||
}
|
||||
|
@ -64,49 +69,45 @@ class ChromeSafariBrowser {
|
|||
assert(url != null && url.isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
if (Platform.isAndroid)
|
||||
optionsMap.addAll(options.android?.toMap() ?? {});
|
||||
else if (Platform.isIOS)
|
||||
optionsMap.addAll(options.ios?.toMap() ?? {});
|
||||
|
||||
Map<String, dynamic> optionsFallbackMap = {};
|
||||
if (optionsFallback != null) {
|
||||
optionsFallbackMap
|
||||
.addAll(optionsFallback.crossPlatform?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback
|
||||
.inAppWebViewWidgetOptions?.crossPlatform
|
||||
?.toMap() ??
|
||||
{});
|
||||
if (Platform.isAndroid) {
|
||||
optionsFallbackMap
|
||||
.addAll(optionsFallback.android?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback
|
||||
.inAppWebViewWidgetOptions?.android
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsFallbackMap
|
||||
.addAll(optionsFallback.ios?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback
|
||||
.inAppWebViewWidgetOptions?.ios
|
||||
?.toMap() ??
|
||||
{});
|
||||
}
|
||||
}
|
||||
List<Map<String, dynamic>> menuItemList = new List();
|
||||
_menuItems.forEach((key, value) {
|
||||
menuItemList.add({
|
||||
"id": value.id,
|
||||
"label": value.label
|
||||
});
|
||||
});
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('url', () => url);
|
||||
args.putIfAbsent('options', () => optionsMap);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
args.putIfAbsent('uuidFallback',
|
||||
() => (browserFallback != null) ? browserFallback.uuid : '');
|
||||
args.putIfAbsent('headersFallback', () => headersFallback);
|
||||
args.putIfAbsent('optionsFallback', () => optionsFallbackMap);
|
||||
args.putIfAbsent('optionsFallback', () => optionsFallback?.toMap() ?? {});
|
||||
args.putIfAbsent('menuItemList', () => menuItemList);
|
||||
await _sharedChannel.invokeMethod('open', args);
|
||||
this._isOpened = true;
|
||||
}
|
||||
|
||||
///Closes the [ChromeSafariBrowser] instance.
|
||||
Future<void> close() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod("close", args);
|
||||
}
|
||||
|
||||
///Adds a [ChromeSafariBrowserMenuItem] to the menu.
|
||||
void addMenuItem(ChromeSafariBrowserMenuItem menuItem) {
|
||||
this._menuItems[menuItem.id] = menuItem;
|
||||
}
|
||||
|
||||
///Adds a list of [ChromeSafariBrowserMenuItem] to the menu.
|
||||
void addMenuItems(List<ChromeSafariBrowserMenuItem> menuItems) {
|
||||
menuItems.forEach((menuItem) {
|
||||
this._menuItems[menuItem.id] = menuItem;
|
||||
});
|
||||
}
|
||||
|
||||
///Event fires when the [ChromeSafariBrowser] is opened.
|
||||
void onOpened() {}
|
||||
|
||||
|
@ -137,3 +138,11 @@ class ChromeSafariBrowser {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ChromeSafariBrowserMenuItem {
|
||||
int id;
|
||||
String label;
|
||||
final void Function(String url, String title) action;
|
||||
|
||||
ChromeSafariBrowserMenuItem({@required this.id, @required this.label, @required this.action});
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'types.dart';
|
||||
|
||||
///ContentBlocker class represents a set of rules to use block content in the browser window.
|
||||
///Class that represents a set of rules to use block content in the browser window.
|
||||
///
|
||||
///On iOS, it uses [WKContentRuleListStore](https://developer.apple.com/documentation/webkit/wkcontentruleliststore).
|
||||
///On Android, it uses a custom implementation because such functionality doesn't exist.
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
|
|||
|
||||
import 'types.dart';
|
||||
|
||||
///CookieManager class implements a singleton object (shared instance) which manages the cookies used by WebView instances.
|
||||
///Class that implements a singleton object (shared instance) which manages the cookies used by WebView instances.
|
||||
///
|
||||
///**NOTE for iOS**: available from iOS 11.0+.
|
||||
class CookieManager {
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'types.dart';
|
||||
import 'webview.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
|
||||
///Class that represents a WebView in headless mode.
|
||||
///It can be used to run a WebView in background without attaching an `InAppWebView` to the widget tree.
|
||||
///
|
||||
///Remember to dispose it when you don't need it anymore.
|
||||
class HeadlessInAppWebView implements WebView {
|
||||
String uuid;
|
||||
bool _isDisposed = true;
|
||||
static const MethodChannel _sharedChannel = const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview');
|
||||
|
||||
///WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||
InAppWebViewController webViewController;
|
||||
|
||||
HeadlessInAppWebView(
|
||||
{this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
this.onLoadStop,
|
||||
this.onLoadError,
|
||||
this.onLoadHttpError,
|
||||
this.onProgressChanged,
|
||||
this.onConsoleMessage,
|
||||
this.shouldOverrideUrlLoading,
|
||||
this.onLoadResource,
|
||||
this.onScrollChanged,
|
||||
this.onDownloadStart,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onJsAlert,
|
||||
this.onJsConfirm,
|
||||
this.onJsPrompt,
|
||||
this.onReceivedHttpAuthRequest,
|
||||
this.onReceivedServerTrustAuthRequest,
|
||||
this.onReceivedClientCertRequest,
|
||||
this.onFindResultReceived,
|
||||
this.shouldInterceptAjaxRequest,
|
||||
this.onAjaxReadyStateChange,
|
||||
this.onAjaxProgress,
|
||||
this.shouldInterceptFetchRequest,
|
||||
this.onUpdateVisitedHistory,
|
||||
this.onPrint,
|
||||
this.onLongPressHitTestResult,
|
||||
this.androidOnSafeBrowsingHit,
|
||||
this.androidOnPermissionRequest,
|
||||
this.androidOnGeolocationPermissionsShowPrompt,
|
||||
this.androidOnGeolocationPermissionsHidePrompt,
|
||||
this.iosOnWebContentProcessDidTerminate,
|
||||
this.iosOnDidCommit,
|
||||
this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
|
||||
this.initialUrl,
|
||||
this.initialFile,
|
||||
this.initialData,
|
||||
this.initialHeaders,
|
||||
this.initialOptions}) {
|
||||
uuid = uuidGenerator.v4();
|
||||
webViewController = new InAppWebViewController(uuid, this);
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case "onHeadlessWebViewCreated":
|
||||
onWebViewCreated(webViewController);
|
||||
break;
|
||||
default:
|
||||
return webViewController.handleMethod(call);
|
||||
}
|
||||
}
|
||||
|
||||
///Runs the headless WebView.
|
||||
Future<void> run() async {
|
||||
if (!_isDisposed) {
|
||||
return;
|
||||
}
|
||||
_isDisposed = false;
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('params', () => <String, dynamic>{
|
||||
'initialUrl': '${Uri.parse(this.initialUrl)}',
|
||||
'initialFile': this.initialFile,
|
||||
'initialData': this.initialData?.toMap(),
|
||||
'initialHeaders': this.initialHeaders,
|
||||
'initialOptions': this.initialOptions?.toMap()
|
||||
});
|
||||
await _sharedChannel.invokeMethod('createHeadlessWebView', args);
|
||||
}
|
||||
|
||||
///Disposes the headless WebView.
|
||||
Future<void> dispose() async {
|
||||
if (_isDisposed) {
|
||||
return;
|
||||
}
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
await _sharedChannel.invokeMethod('disposeHeadlessWebView', args);
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
@override
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(
|
||||
InAppWebViewController controller, String origin)
|
||||
androidOnGeolocationPermissionsShowPrompt;
|
||||
|
||||
@override
|
||||
final Future<PermissionRequestResponse> Function(
|
||||
InAppWebViewController controller,
|
||||
String origin,
|
||||
List<String> resources) androidOnPermissionRequest;
|
||||
|
||||
@override
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat threatType) androidOnSafeBrowsingHit;
|
||||
|
||||
@override
|
||||
final InAppWebViewInitialData initialData;
|
||||
|
||||
@override
|
||||
final String initialFile;
|
||||
|
||||
@override
|
||||
final Map<String, String> initialHeaders;
|
||||
|
||||
@override
|
||||
final InAppWebViewGroupOptions initialOptions;
|
||||
|
||||
@override
|
||||
final String initialUrl;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller) iosOnDidCommit;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
@override
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
onAjaxProgress;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
onAjaxReadyStateChange;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)
|
||||
onConsoleMessage;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller,
|
||||
OnCreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onDownloadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting) onFindResultReceived;
|
||||
|
||||
@override
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsAlert;
|
||||
|
||||
@override
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsConfirm;
|
||||
|
||||
@override
|
||||
final Future<JsPromptResponse> Function(InAppWebViewController controller,
|
||||
String message, String defaultValue) onJsPrompt;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
String message) onLoadError;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url,
|
||||
int statusCode, String description) onLoadHttpError;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoadedResource resource)
|
||||
onLoadResource;
|
||||
|
||||
@override
|
||||
final Future<CustomSchemeResponse> Function(
|
||||
InAppWebViewController controller, String scheme, String url)
|
||||
onLoadResourceCustomScheme;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onLoadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller,
|
||||
LongPressHitTestResult hitTestResult) onLongPressHitTestResult;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, String url) onPrint;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int progress)
|
||||
onProgressChanged;
|
||||
|
||||
@override
|
||||
final Future<ClientCertResponse> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)
|
||||
onReceivedClientCertRequest;
|
||||
|
||||
@override
|
||||
final Future<HttpAuthResponse> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)
|
||||
onReceivedHttpAuthRequest;
|
||||
|
||||
@override
|
||||
final Future<ServerTrustAuthResponse> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)
|
||||
onReceivedServerTrustAuthRequest;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int x, int y)
|
||||
onScrollChanged;
|
||||
|
||||
@override
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool androidIsReload)
|
||||
onUpdateVisitedHistory;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
|
||||
@override
|
||||
final Future<AjaxRequest> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
shouldInterceptAjaxRequest;
|
||||
|
||||
@override
|
||||
final Future<FetchRequest> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)
|
||||
shouldInterceptFetchRequest;
|
||||
|
||||
@override
|
||||
final Future<ShouldOverrideUrlLoadingAction> Function(
|
||||
InAppWebViewController controller,
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)
|
||||
shouldOverrideUrlLoading;
|
||||
}
|
|
@ -5,7 +5,7 @@ import 'package:flutter/foundation.dart';
|
|||
import 'types.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
///HttpAuthCredentialDatabase class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache.
|
||||
///Class that implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache.
|
||||
///On iOS, this class uses the [URLCredentialStorage](https://developer.apple.com/documentation/foundation/urlcredentialstorage) class.
|
||||
///On Android, this class has a custom implementation using `android.database.sqlite.SQLiteDatabase` because [WebViewDatabase](https://developer.android.com/reference/android/webkit/WebViewDatabase)
|
||||
///doesn't offer the same functionalities as iOS `URLCredentialStorage`.
|
||||
|
|
|
@ -4,14 +4,13 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
import 'webview_options.dart';
|
||||
|
||||
import 'types.dart';
|
||||
import 'in_app_webview.dart' show InAppWebViewController;
|
||||
|
||||
///InAppBrowser class. [webViewController] can be used to access the [InAppWebView] API.
|
||||
///
|
||||
///This class uses the native WebView of the platform.
|
||||
///The [webViewController] field can be used to access the [InAppWebViewController] API.
|
||||
class InAppBrowser {
|
||||
String uuid;
|
||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
|
||||
|
@ -20,7 +19,7 @@ class InAppBrowser {
|
|||
MethodChannel _channel;
|
||||
static const MethodChannel _sharedChannel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
|
||||
|
||||
/// WebView Controller that can be used to access the [InAppWebView] API.
|
||||
/// WebView Controller that can be used to access the [InAppWebViewController] API.
|
||||
InAppWebViewController webViewController;
|
||||
|
||||
///
|
||||
|
@ -63,29 +62,11 @@ class InAppBrowser {
|
|||
assert(url != null && url.isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.android?.toMap() ?? {});
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.android
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.ios?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('url', () => url);
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('options', () => optionsMap);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
await _sharedChannel.invokeMethod('openUrl', args);
|
||||
}
|
||||
|
||||
|
@ -129,29 +110,13 @@ class InAppBrowser {
|
|||
assert(assetFilePath != null && assetFilePath.isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.android?.toMap() ?? {});
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.android
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.ios?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('url', () => assetFilePath);
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('options', () => optionsMap);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
await _sharedChannel.invokeMethod('openFile', args);
|
||||
}
|
||||
|
||||
|
@ -173,27 +138,9 @@ class InAppBrowser {
|
|||
InAppBrowserClassOptions options}) async {
|
||||
assert(data != null);
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.android?.toMap() ?? {});
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.android
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.ios?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('options', () => optionsMap);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
args.putIfAbsent('data', () => data);
|
||||
args.putIfAbsent('mimeType', () => mimeType);
|
||||
args.putIfAbsent('encoding', () => encoding);
|
||||
|
@ -243,26 +190,8 @@ class InAppBrowser {
|
|||
Future<void> setOptions({@required InAppBrowserClassOptions options}) async {
|
||||
this.throwIsNotOpened();
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.android?.toMap() ?? {});
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.android
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.ios?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('options', () => optionsMap);
|
||||
args.putIfAbsent('options', () => options?.toMap() ?? {});
|
||||
await _channel.invokeMethod('setOptions', args);
|
||||
}
|
||||
|
||||
|
@ -279,19 +208,19 @@ class InAppBrowser {
|
|||
options = options.cast<String, dynamic>();
|
||||
inAppBrowserClassOptions.crossPlatform =
|
||||
InAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions = InAppWebViewWidgetOptions();
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions.crossPlatform =
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions = InAppWebViewGroupOptions();
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.crossPlatform =
|
||||
InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid) {
|
||||
inAppBrowserClassOptions.android =
|
||||
AndroidInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions
|
||||
.inAppWebViewWidgetOptions.android =
|
||||
.inAppWebViewGroupOptions.android =
|
||||
AndroidInAppWebViewOptions.fromMap(options);
|
||||
} else if (Platform.isIOS) {
|
||||
inAppBrowserClassOptions.ios =
|
||||
IOSInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions
|
||||
.ios = IOSInAppWebViewOptions.fromMap(options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import 'dart:async';
|
|||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
///InAppLocalhostServer class.
|
||||
///
|
||||
///This class allows you to create a simple server on `http://localhost:[port]/` in order to be able to load your assets file on a server. The default [port] value is `8080`.
|
||||
class InAppLocalhostServer {
|
||||
HttpServer _server;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'webview_options.dart';
|
||||
|
@ -183,8 +182,6 @@ class ConsoleMessage {
|
|||
{this.message = "", this.messageLevel = ConsoleMessageLevel.LOG});
|
||||
}
|
||||
|
||||
///WebHistory class.
|
||||
///
|
||||
///This class contains a snapshot of the current back/forward list for a WebView.
|
||||
class WebHistory {
|
||||
///List of all [WebHistoryItem]s.
|
||||
|
@ -196,8 +193,6 @@ class WebHistory {
|
|||
WebHistory({this.list, this.currentIndex});
|
||||
}
|
||||
|
||||
///WebHistoryItem class.
|
||||
///
|
||||
///A convenience class for accessing fields in an entry in the back/forward list of a WebView. Each WebHistoryItem is a snapshot of the requested history item.
|
||||
class WebHistoryItem {
|
||||
///Original url of this history item.
|
||||
|
@ -219,8 +214,6 @@ class WebHistoryItem {
|
|||
{this.originalUrl, this.title, this.url, this.index, this.offset});
|
||||
}
|
||||
|
||||
///GeolocationPermissionPromptResponse class.
|
||||
///
|
||||
///Class used by the host application to set the Geolocation permission state for an origin during the [androidOnGeolocationPermissionsShowPrompt] event.
|
||||
class GeolocationPermissionShowPromptResponse {
|
||||
///The origin for which permissions are set.
|
||||
|
@ -240,7 +233,7 @@ class GeolocationPermissionShowPromptResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///JsAlertResponseAction class used by [JsAlertResponse] class.
|
||||
///Class used by [JsAlertResponse] class.
|
||||
class JsAlertResponseAction {
|
||||
final int _value;
|
||||
const JsAlertResponseAction._internal(this._value);
|
||||
|
@ -254,7 +247,7 @@ class JsAlertResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///JsAlertResponse class represents the response used by the [onJsAlert] event to control a JavaScript alert dialog.
|
||||
///Class represents the response used by the [onJsAlert] event to control a JavaScript alert dialog.
|
||||
class JsAlertResponse {
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
@ -284,7 +277,7 @@ class JsAlertResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///JsConfirmResponseAction class used by [JsConfirmResponse] class.
|
||||
///Class used by [JsConfirmResponse] class.
|
||||
class JsConfirmResponseAction {
|
||||
final int _value;
|
||||
const JsConfirmResponseAction._internal(this._value);
|
||||
|
@ -299,7 +292,7 @@ class JsConfirmResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///JsConfirmResponse class represents the response used by the [onJsConfirm] event to control a JavaScript confirm dialog.
|
||||
///Class that represents the response used by the [onJsConfirm] event to control a JavaScript confirm dialog.
|
||||
class JsConfirmResponse {
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
@ -334,7 +327,7 @@ class JsConfirmResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///JsPromptResponseAction class used by [JsPromptResponse] class.
|
||||
///Class used by [JsPromptResponse] class.
|
||||
class JsPromptResponseAction {
|
||||
final int _value;
|
||||
const JsPromptResponseAction._internal(this._value);
|
||||
|
@ -349,7 +342,7 @@ class JsPromptResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///JsPromptResponse class represents the response used by the [onJsPrompt] event to control a JavaScript prompt dialog.
|
||||
///Class that represents the response used by the [onJsPrompt] event to control a JavaScript prompt dialog.
|
||||
class JsPromptResponse {
|
||||
///Message to be displayed in the window.
|
||||
String message;
|
||||
|
@ -394,7 +387,7 @@ class JsPromptResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///SafeBrowsingThreat class represents the reason the resource was caught by Safe Browsing.
|
||||
///Class that represents the reason the resource was caught by Safe Browsing.
|
||||
class SafeBrowsingThreat {
|
||||
final int _value;
|
||||
const SafeBrowsingThreat._internal(this._value);
|
||||
|
@ -438,7 +431,7 @@ class SafeBrowsingThreat {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///SafeBrowsingResponseAction class used by [SafeBrowsingResponse] class.
|
||||
///Class used by [SafeBrowsingResponse] class.
|
||||
class SafeBrowsingResponseAction {
|
||||
final int _value;
|
||||
const SafeBrowsingResponseAction._internal(this._value);
|
||||
|
@ -460,7 +453,7 @@ class SafeBrowsingResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///SafeBrowsingResponse class represents the response used by the [androidOnSafeBrowsingHit] event.
|
||||
///Class that represents the response used by the [androidOnSafeBrowsingHit] event.
|
||||
///It is used to indicate an action to take when hitting a malicious URL.
|
||||
class SafeBrowsingResponse {
|
||||
///If reporting is enabled, all reports will be sent according to the privacy policy referenced by [InAppWebViewController.androidGetSafeBrowsingPrivacyPolicyUrl].
|
||||
|
@ -478,7 +471,7 @@ class SafeBrowsingResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///HttpAuthResponseAction class used by [HttpAuthResponse] class.
|
||||
///Class used by [HttpAuthResponse] class.
|
||||
class HttpAuthResponseAction {
|
||||
final int _value;
|
||||
const HttpAuthResponseAction._internal(this._value);
|
||||
|
@ -500,7 +493,7 @@ class HttpAuthResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///HttpAuthResponse class represents the response used by the [onReceivedHttpAuthRequest] event.
|
||||
///Class that represents the response used by the [onReceivedHttpAuthRequest] event.
|
||||
class HttpAuthResponse {
|
||||
///Represents the username used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED]
|
||||
String username;
|
||||
|
@ -530,7 +523,7 @@ class HttpAuthResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///HttpAuthChallenge class represents the challenge of the [onReceivedHttpAuthRequest] event.
|
||||
///Class that represents the challenge of the [onReceivedHttpAuthRequest] event.
|
||||
///It provides all the information about the challenge.
|
||||
class HttpAuthChallenge {
|
||||
///A count of previous failed authentication attempts.
|
||||
|
@ -544,7 +537,7 @@ class HttpAuthChallenge {
|
|||
: assert(previousFailureCount != null && protectionSpace != null);
|
||||
}
|
||||
|
||||
///ProtectionSpace class represents a protection space requiring authentication.
|
||||
///Class that represents a protection space requiring authentication.
|
||||
class ProtectionSpace {
|
||||
///The hostname of the server.
|
||||
String host;
|
||||
|
@ -565,7 +558,7 @@ class ProtectionSpace {
|
|||
: assert(host != null && protocol != null);
|
||||
}
|
||||
|
||||
///HttpAuthCredential represents the credentials of an http authentication.
|
||||
///Class that represents the credentials of an http authentication.
|
||||
///It is used by the [HttpAuthCredentialDatabase] class.
|
||||
class HttpAuthCredential {
|
||||
///Represents the username.
|
||||
|
@ -578,7 +571,7 @@ class HttpAuthCredential {
|
|||
: assert(username != null && password != null);
|
||||
}
|
||||
|
||||
///ServerTrustAuthResponseAction class used by [ServerTrustAuthResponse] class.
|
||||
///Class used by [ServerTrustAuthResponse] class.
|
||||
class ServerTrustAuthResponseAction {
|
||||
final int _value;
|
||||
const ServerTrustAuthResponseAction._internal(this._value);
|
||||
|
@ -608,7 +601,7 @@ class ServerTrustAuthResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///ServerTrustChallenge class represents the challenge of the [onReceivedServerTrustAuthRequest] event.
|
||||
///Class that represents the challenge of the [onReceivedServerTrustAuthRequest] event.
|
||||
///It provides all the information about the challenge.
|
||||
class ServerTrustChallenge {
|
||||
///The protection space requiring authentication.
|
||||
|
@ -635,7 +628,7 @@ class ServerTrustChallenge {
|
|||
: assert(protectionSpace != null && error != null);
|
||||
}
|
||||
|
||||
///ClientCertResponseAction class used by [ClientCertResponse] class.
|
||||
///Class used by [ClientCertResponse] class.
|
||||
class ClientCertResponseAction {
|
||||
final int _value;
|
||||
const ClientCertResponseAction._internal(this._value);
|
||||
|
@ -656,7 +649,7 @@ class ClientCertResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///ClientCertResponse class represents the response used by the [onReceivedClientCertRequest] event.
|
||||
///Class that represents the response used by the [onReceivedClientCertRequest] event.
|
||||
class ClientCertResponse {
|
||||
///The file path of the certificate to use.
|
||||
String certificatePath;
|
||||
|
@ -689,7 +682,7 @@ class ClientCertResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///ClientCertChallenge class represents the challenge of the [onReceivedClientCertRequest] event.
|
||||
///Class that represents the challenge of the [onReceivedClientCertRequest] event.
|
||||
///It provides all the information about the challenge.
|
||||
class ClientCertChallenge {
|
||||
///The protection space requiring authentication.
|
||||
|
@ -699,7 +692,7 @@ class ClientCertChallenge {
|
|||
: assert(protectionSpace != null);
|
||||
}
|
||||
|
||||
///Favicon class represents a favicon of a website. It is used by [InAppWebViewController.getFavicons] method.
|
||||
///Class that represents a favicon of a website. It is used by [InAppWebViewController.getFavicons] method.
|
||||
class Favicon {
|
||||
///The url of the favicon image.
|
||||
String url;
|
||||
|
@ -721,7 +714,7 @@ class Favicon {
|
|||
}
|
||||
}
|
||||
|
||||
///AndroidCacheMode class represents an Android-specific class used to override the way the cache is used.
|
||||
///Class that represents an Android-specific class used to override the way the cache is used.
|
||||
class AndroidCacheMode {
|
||||
final int _value;
|
||||
const AndroidCacheMode._internal(this._value);
|
||||
|
@ -768,7 +761,7 @@ class AndroidCacheMode {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///AndroidActionModeMenuItem class represents an Android-specific class used to disable the action mode menu items.
|
||||
///Class that represents an Android-specific class used to disable the action mode menu items.
|
||||
///
|
||||
///**NOTE**: available on Android 24+.
|
||||
class AndroidActionModeMenuItem {
|
||||
|
@ -818,7 +811,7 @@ class AndroidActionModeMenuItem {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///AndroidForceDark class represents an Android-specific class used to indicate the force dark mode.
|
||||
///Class that represents an Android-specific class used to indicate the force dark mode.
|
||||
///
|
||||
///**NOTE**: available on Android 29+.
|
||||
class AndroidForceDark {
|
||||
|
@ -861,7 +854,7 @@ class AndroidForceDark {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///AndroidLayoutAlgorithm class represents an Android-specific class used to set the underlying layout algorithm.
|
||||
///Class that represents an Android-specific class used to set the underlying layout algorithm.
|
||||
class AndroidLayoutAlgorithm {
|
||||
final String _value;
|
||||
const AndroidLayoutAlgorithm._internal(this._value);
|
||||
|
@ -892,7 +885,7 @@ class AndroidLayoutAlgorithm {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///AndroidMixedContentMode class represents an Android-specific class used to configure the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
|
||||
///Class that represents an Android-specific class used to configure the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
class AndroidMixedContentMode {
|
||||
|
@ -942,7 +935,7 @@ class AndroidMixedContentMode {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///IOSWKSelectionGranularity class represents an iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view.
|
||||
///Class that represents an iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view.
|
||||
class IOSWKSelectionGranularity {
|
||||
final int _value;
|
||||
const IOSWKSelectionGranularity._internal(this._value);
|
||||
|
@ -977,7 +970,7 @@ class IOSWKSelectionGranularity {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///IOSWKDataDetectorTypes class represents an iOS-specific class used to specify a dataDetectoryTypes value that adds interactivity to web content that matches the value.
|
||||
///Class that represents an iOS-specific class used to specify a dataDetectoryTypes value that adds interactivity to web content that matches the value.
|
||||
///
|
||||
///**NOTE**: available on iOS 10.0+.
|
||||
class IOSWKDataDetectorTypes {
|
||||
|
@ -1048,7 +1041,7 @@ class IOSWKDataDetectorTypes {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///IOSUIScrollViewDecelerationRate class represents a floating-point value that determines the rate of deceleration after the user lifts their finger.
|
||||
///Class that represents a floating-point value that determines the rate of deceleration after the user lifts their finger.
|
||||
class IOSUIScrollViewDecelerationRate {
|
||||
final String _value;
|
||||
const IOSUIScrollViewDecelerationRate._internal(this._value);
|
||||
|
@ -1077,7 +1070,7 @@ class IOSUIScrollViewDecelerationRate {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///UserPreferredContentMode class represents the content mode to prefer when loading and rendering a webpage.
|
||||
///Class that represents the content mode to prefer when loading and rendering a webpage.
|
||||
class UserPreferredContentMode {
|
||||
final int _value;
|
||||
const UserPreferredContentMode._internal(this._value);
|
||||
|
@ -1118,7 +1111,7 @@ class UserPreferredContentMode {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///IOSUIModalPresentationStyle class represents an iOS-specific class used to specify the modal presentation style when presenting a view controller.
|
||||
///Class that represents an iOS-specific class used to specify the modal presentation style when presenting a view controller.
|
||||
class IOSUIModalPresentationStyle {
|
||||
final int _value;
|
||||
const IOSUIModalPresentationStyle._internal(this._value);
|
||||
|
@ -1201,7 +1194,7 @@ class IOSUIModalPresentationStyle {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///IOSUIModalTransitionStyle class represents an iOS-specific class used to specify the transition style when presenting a view controller.
|
||||
///Class that represents an iOS-specific class used to specify the transition style when presenting a view controller.
|
||||
class IOSUIModalTransitionStyle {
|
||||
final int _value;
|
||||
const IOSUIModalTransitionStyle._internal(this._value);
|
||||
|
@ -1255,7 +1248,7 @@ class IOSUIModalTransitionStyle {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///IOSSafariDismissButtonStyle class represents an iOS-specific class used to set the custom style for the dismiss button.
|
||||
///Class that represents an iOS-specific class used to set the custom style for the dismiss button.
|
||||
///
|
||||
///**NOTE**: available on iOS 11.0+.
|
||||
class IOSSafariDismissButtonStyle {
|
||||
|
@ -1296,8 +1289,8 @@ class IOSSafariDismissButtonStyle {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///InAppWebViewWidgetOptions class represents the options that can be used for an [InAppWebView].
|
||||
class InAppWebViewWidgetOptions {
|
||||
///Class that represents the options that can be used for a [WebView].
|
||||
class InAppWebViewGroupOptions {
|
||||
///Cross-platform options.
|
||||
InAppWebViewOptions crossPlatform;
|
||||
|
||||
|
@ -1307,13 +1300,28 @@ class InAppWebViewWidgetOptions {
|
|||
///iOS-specific options.
|
||||
IOSInAppWebViewOptions ios;
|
||||
|
||||
InAppWebViewWidgetOptions(
|
||||
InAppWebViewGroupOptions(
|
||||
{this.crossPlatform,
|
||||
this.android,
|
||||
this.ios});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
Map<String, dynamic> options = {};
|
||||
options.addAll(this.crossPlatform?.toMap() ?? {});
|
||||
if (Platform.isAndroid)
|
||||
options.addAll(this.android?.toMap() ?? {});
|
||||
else if (Platform.isIOS)
|
||||
options.addAll(this.ios?.toMap() ?? {});
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
}
|
||||
|
||||
///InAppBrowserClassOptions class represents the options that can be used for an [InAppBrowser] WebView.
|
||||
///Class that represents the options that can be used for an [InAppBrowser] WebView.
|
||||
class InAppBrowserClassOptions {
|
||||
///Cross-platform options.
|
||||
InAppBrowserOptions crossPlatform;
|
||||
|
@ -1325,16 +1333,42 @@ class InAppBrowserClassOptions {
|
|||
IOSInAppBrowserOptions ios;
|
||||
|
||||
///WebView options.
|
||||
InAppWebViewWidgetOptions inAppWebViewWidgetOptions;
|
||||
InAppWebViewGroupOptions inAppWebViewGroupOptions;
|
||||
|
||||
InAppBrowserClassOptions(
|
||||
{this.crossPlatform,
|
||||
this.android,
|
||||
this.ios,
|
||||
this.inAppWebViewWidgetOptions});
|
||||
this.inAppWebViewGroupOptions});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
Map<String, dynamic> options = {};
|
||||
|
||||
options.addAll(this.crossPlatform?.toMap() ?? {});
|
||||
options.addAll(
|
||||
this.inAppWebViewGroupOptions?.crossPlatform?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
options.addAll(this.android?.toMap() ?? {});
|
||||
options.addAll(this
|
||||
.inAppWebViewGroupOptions?.android
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
options.addAll(this.ios?.toMap() ?? {});
|
||||
options.addAll(
|
||||
this.inAppWebViewGroupOptions?.ios?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
}
|
||||
|
||||
///ChromeSafariBrowserClassOptions class represents the options that can be used for an [ChromeSafariBrowser] window.
|
||||
///Class that represents the options that can be used for an [ChromeSafariBrowser] window.
|
||||
class ChromeSafariBrowserClassOptions {
|
||||
///Android-specific options.
|
||||
AndroidChromeCustomTabsOptions android;
|
||||
|
@ -1344,9 +1378,23 @@ class ChromeSafariBrowserClassOptions {
|
|||
|
||||
ChromeSafariBrowserClassOptions(
|
||||
{this.android, this.ios});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
Map<String, dynamic> options = {};
|
||||
if (Platform.isAndroid)
|
||||
options.addAll(this.android?.toMap() ?? {});
|
||||
else if (Platform.isIOS)
|
||||
options.addAll(this.ios?.toMap() ?? {});
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
}
|
||||
|
||||
///AjaxRequestAction class used by [AjaxRequest] class.
|
||||
///Class used by [AjaxRequest] class.
|
||||
class AjaxRequestAction {
|
||||
final int _value;
|
||||
const AjaxRequestAction._internal(this._value);
|
||||
|
@ -1374,7 +1422,7 @@ class AjaxRequestAction {
|
|||
}
|
||||
}
|
||||
|
||||
///AjaxRequestEventType class used by [AjaxRequestEvent] class.
|
||||
///Class used by [AjaxRequestEvent] class.
|
||||
class AjaxRequestEventType {
|
||||
final String _value;
|
||||
const AjaxRequestEventType._internal(this._value);
|
||||
|
@ -1416,7 +1464,7 @@ class AjaxRequestEventType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///AjaxRequestEvent class used by [AjaxRequest] class. It represents events measuring progress of an [AjaxRequest].
|
||||
///Class used by [AjaxRequest] class. It represents events measuring progress of an [AjaxRequest].
|
||||
class AjaxRequestEvent {
|
||||
///Event type.
|
||||
AjaxRequestEventType type;
|
||||
|
@ -1437,7 +1485,7 @@ class AjaxRequestEvent {
|
|||
AjaxRequestEvent({this.type, this.lengthComputable, this.loaded, this.total});
|
||||
}
|
||||
|
||||
///AjaxRequestReadyState class used by [AjaxRequest] class. It represents the state of an [AjaxRequest].
|
||||
///Class used by [AjaxRequest] class. It represents the state of an [AjaxRequest].
|
||||
class AjaxRequestReadyState {
|
||||
final int _value;
|
||||
const AjaxRequestReadyState._internal(this._value);
|
||||
|
@ -1486,7 +1534,7 @@ class AjaxRequestReadyState {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///AjaxRequestHeaders class represents the HTTP headers of an [AjaxRequest].
|
||||
///Class that represents the HTTP headers of an [AjaxRequest].
|
||||
class AjaxRequestHeaders {
|
||||
Map<dynamic, dynamic> _headers;
|
||||
Map<String, dynamic> _newHeaders = {};
|
||||
|
@ -1511,7 +1559,7 @@ class AjaxRequestHeaders {
|
|||
}
|
||||
}
|
||||
|
||||
///AjaxRequest class represents a JavaScript [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) object.
|
||||
///Class that represents a JavaScript [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) object.
|
||||
class AjaxRequest {
|
||||
///Data passed as a parameter to the `XMLHttpRequest.send()` method.
|
||||
dynamic data;
|
||||
|
@ -1629,7 +1677,7 @@ class AjaxRequest {
|
|||
}
|
||||
}
|
||||
|
||||
///FetchRequestAction class used by [FetchRequest] class.
|
||||
///Class used by [FetchRequest] class.
|
||||
class FetchRequestAction {
|
||||
final int _value;
|
||||
const FetchRequestAction._internal(this._value);
|
||||
|
@ -1647,7 +1695,7 @@ class FetchRequestAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///FetchRequestCredential class is an interface for [FetchRequestCredentialDefault], [FetchRequestFederatedCredential] and [FetchRequestPasswordCredential] classes.
|
||||
///Class that is an interface for [FetchRequestCredentialDefault], [FetchRequestFederatedCredential] and [FetchRequestPasswordCredential] classes.
|
||||
class FetchRequestCredential {
|
||||
///Type of credentials.
|
||||
String type;
|
||||
|
@ -1659,7 +1707,7 @@ class FetchRequestCredential {
|
|||
}
|
||||
}
|
||||
|
||||
///FetchRequestCredentialDefault class represents the default credentials used by an [FetchRequest].
|
||||
///Class that represents the default credentials used by an [FetchRequest].
|
||||
class FetchRequestCredentialDefault extends FetchRequestCredential {
|
||||
///The value of the credentials.
|
||||
String value;
|
||||
|
@ -1674,7 +1722,7 @@ class FetchRequestCredentialDefault extends FetchRequestCredential {
|
|||
}
|
||||
}
|
||||
|
||||
///FetchRequestFederatedCredential class represents a [FederatedCredential](https://developer.mozilla.org/en-US/docs/Web/API/FederatedCredential) type of credentials.
|
||||
///Class that represents a [FederatedCredential](https://developer.mozilla.org/en-US/docs/Web/API/FederatedCredential) type of credentials.
|
||||
class FetchRequestFederatedCredential extends FetchRequestCredential {
|
||||
///Credential's identifier.
|
||||
dynamic id;
|
||||
|
@ -1707,7 +1755,7 @@ class FetchRequestFederatedCredential extends FetchRequestCredential {
|
|||
}
|
||||
}
|
||||
|
||||
///FetchRequestPasswordCredential class represents a [PasswordCredential](https://developer.mozilla.org/en-US/docs/Web/API/PasswordCredential) type of credentials.
|
||||
///Class that represents a [PasswordCredential](https://developer.mozilla.org/en-US/docs/Web/API/PasswordCredential) type of credentials.
|
||||
class FetchRequestPasswordCredential extends FetchRequestCredential {
|
||||
///Credential's identifier.
|
||||
dynamic id;
|
||||
|
@ -1736,7 +1784,7 @@ class FetchRequestPasswordCredential extends FetchRequestCredential {
|
|||
}
|
||||
}
|
||||
|
||||
///FetchRequest class represents a HTTP request created with JavaScript using the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch).
|
||||
///Class that represents a HTTP request created with JavaScript using the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch).
|
||||
class FetchRequest {
|
||||
///The URL of the request.
|
||||
String url;
|
||||
|
@ -1841,7 +1889,7 @@ class FetchRequest {
|
|||
}
|
||||
}
|
||||
|
||||
///ContentBlockerTriggerResourceType class represents the possible resource type defined for a [ContentBlockerTrigger].
|
||||
///Class that represents the possible resource type defined for a [ContentBlockerTrigger].
|
||||
class ContentBlockerTriggerResourceType {
|
||||
final String _value;
|
||||
const ContentBlockerTriggerResourceType._internal(this._value);
|
||||
|
@ -1887,7 +1935,7 @@ class ContentBlockerTriggerResourceType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///ContentBlockerTriggerLoadType class represents the possible load type for a [ContentBlockerTrigger].
|
||||
///Class that represents the possible load type for a [ContentBlockerTrigger].
|
||||
class ContentBlockerTriggerLoadType {
|
||||
final String _value;
|
||||
const ContentBlockerTriggerLoadType._internal(this._value);
|
||||
|
@ -1915,7 +1963,7 @@ class ContentBlockerTriggerLoadType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///ContentBlockerActionType class represents the kind of action that can be used with a [ContentBlockerTrigger].
|
||||
///Class that represents the kind of action that can be used with a [ContentBlockerTrigger].
|
||||
class ContentBlockerActionType {
|
||||
final String _value;
|
||||
const ContentBlockerActionType._internal(this._value);
|
||||
|
@ -1948,7 +1996,7 @@ class ContentBlockerActionType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Cookie class represents a cookie returned by the [CookieManager].
|
||||
///Class that represents a cookie returned by the [CookieManager].
|
||||
class Cookie {
|
||||
///The name;
|
||||
String name;
|
||||
|
@ -1959,7 +2007,7 @@ class Cookie {
|
|||
Cookie({@required this.name, @required this.value});
|
||||
}
|
||||
|
||||
///PermissionRequestResponseAction class used by [PermissionRequestResponse] class.
|
||||
///Class used by [PermissionRequestResponse] class.
|
||||
class PermissionRequestResponseAction {
|
||||
final int _value;
|
||||
const PermissionRequestResponseAction._internal(this._value);
|
||||
|
@ -1977,7 +2025,7 @@ class PermissionRequestResponseAction {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///PermissionRequestResponse class represents the response used by the [androidOnPermissionRequest] event.
|
||||
///Class that represents the response used by the [androidOnPermissionRequest] event.
|
||||
class PermissionRequestResponse {
|
||||
///Resources granted to be accessed by origin.
|
||||
List<String> resources;
|
||||
|
@ -1994,7 +2042,7 @@ class PermissionRequestResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///ShouldOverrideUrlLoadingAction class is used by [shouldOverrideUrlLoading] event.
|
||||
///Class that is used by [shouldOverrideUrlLoading] event.
|
||||
///It represents the policy to pass back to the decision handler.
|
||||
class ShouldOverrideUrlLoadingAction {
|
||||
final int _value;
|
||||
|
@ -2019,7 +2067,7 @@ class ShouldOverrideUrlLoadingAction {
|
|||
}
|
||||
}
|
||||
|
||||
///IOSWKNavigationType class represents the type of action triggering a navigation on iOS for the [shouldOverrideUrlLoading] event.
|
||||
///Class that represents the type of action triggering a navigation on iOS for the [shouldOverrideUrlLoading] event.
|
||||
class IOSWKNavigationType {
|
||||
final int _value;
|
||||
const IOSWKNavigationType._internal(this._value);
|
||||
|
@ -2054,7 +2102,7 @@ class IOSWKNavigationType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///ShouldOverrideUrlLoadingAction class represents the navigation request used by the [shouldOverrideUrlLoading] event.
|
||||
///Class that represents the navigation request used by the [shouldOverrideUrlLoading] event.
|
||||
class ShouldOverrideUrlLoadingRequest {
|
||||
///Represents the url of the navigation request.
|
||||
String url;
|
||||
|
@ -2085,7 +2133,7 @@ class ShouldOverrideUrlLoadingRequest {
|
|||
ShouldOverrideUrlLoadingRequest({this.url, this.method, this.headers, this.isForMainFrame, this.androidHasGesture, this.androidIsRedirect, this.iosWKNavigationType});
|
||||
}
|
||||
|
||||
///OnCreateWindowRequest class represents the navigation request used by the [shouldOverrideUrlLoading] event.
|
||||
///Class that represents the navigation request used by the [shouldOverrideUrlLoading] event.
|
||||
class OnCreateWindowRequest {
|
||||
///Represents the url of the navigation request.
|
||||
String url;
|
||||
|
@ -2102,7 +2150,7 @@ class OnCreateWindowRequest {
|
|||
OnCreateWindowRequest({this.url, this.androidIsDialog, this.androidIsUserGesture, this.iosWKNavigationType});
|
||||
}
|
||||
|
||||
///AndroidWebStorage class encapsulates information about the amount of storage currently used by an origin for the JavaScript storage APIs.
|
||||
///Class that encapsulates information about the amount of storage currently used by an origin for the JavaScript storage APIs.
|
||||
///An origin comprises the host, scheme and port of a URI. See [AndroidWebStorageManager] for details.
|
||||
class AndroidWebStorageOrigin {
|
||||
///The string representation of this origin.
|
||||
|
@ -2129,7 +2177,7 @@ class AndroidWebStorageOrigin {
|
|||
}
|
||||
}
|
||||
|
||||
///IOSWKWebsiteDataType class represents a website data type.
|
||||
///Class that represents a website data type.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
class IOSWKWebsiteDataType {
|
||||
|
@ -2220,7 +2268,7 @@ class IOSWKWebsiteDataType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///WKWebsiteDataRecord class represents website data, grouped by domain name using the public suffix list.
|
||||
///Class that represents website data, grouped by domain name using the public suffix list.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
class IOSWKWebsiteDataRecord {
|
||||
|
@ -2306,7 +2354,7 @@ class LongPressHitTestResultType {
|
|||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///LongPressHitTestResult class represents the hit result for hitting an HTML elements. Used by [onLongPressHitTestResult] event.
|
||||
///Class that represents the hit result for hitting an HTML elements. Used by [onLongPressHitTestResult] event.
|
||||
class LongPressHitTestResult {
|
||||
///The type of the hit test result.
|
||||
LongPressHitTestResultType type;
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
|
|||
|
||||
import 'types.dart';
|
||||
|
||||
///WebStorageManager class implements a singleton object (shared instance) which manages the web storage used by WebView instances.
|
||||
///Class that implements a singleton object (shared instance) which manages the web storage used by WebView instances.
|
||||
///
|
||||
///**NOTE for iOS**: available from iOS 9.0+.
|
||||
class WebStorageManager {
|
||||
|
@ -30,7 +30,7 @@ class WebStorageManager {
|
|||
static Future<dynamic> _handleMethod(MethodCall call) async {}
|
||||
}
|
||||
|
||||
///AndroidWebStorageManager class is used to manage the JavaScript storage APIs provided by the WebView.
|
||||
///Class that is used to manage the JavaScript storage APIs provided by the WebView.
|
||||
///It manages the Application Cache API, the Web SQL Database API and the HTML5 Web Storage API.
|
||||
class AndroidWebStorageManager {
|
||||
///Gets the origins currently using either the Application Cache or Web SQL Database APIs.
|
||||
|
@ -83,7 +83,7 @@ class AndroidWebStorageManager {
|
|||
}
|
||||
}
|
||||
|
||||
///IOSWebStorageManager class represents various types of data that a website might make use of.
|
||||
///Class that represents various types of data that a website might make use of.
|
||||
///This includes cookies, disk and memory caches, and persistent data such as WebSQL, IndexedDB databases, and local storage.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
import 'types.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
|
||||
///Abstract class that represents a WebView. Used by [WebView] and [HeadlessInAppWebView].
|
||||
abstract class WebView {
|
||||
///Event fired when the [WebView] is created.
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
|
||||
///Event fired when the [WebView] starts to load an [url].
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onLoadStart;
|
||||
|
||||
///Event fired when the [WebView] finishes loading an [url].
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
|
||||
///Event fired when the [WebView] encounters an error loading an [url].
|
||||
final void Function(InAppWebViewController controller, String url, int code,
|
||||
String message) onLoadError;
|
||||
|
||||
///Event fired when the [WebView] main page receives an HTTP error.
|
||||
///
|
||||
///[url] represents the url of the main page that received the HTTP error.
|
||||
///
|
||||
///[statusCode] represents the status code of the response. HTTP errors have status codes >= 400.
|
||||
///
|
||||
///[description] represents the description of the HTTP error. On iOS, it is always an empty string.
|
||||
///
|
||||
///**NOTE**: available on Android 23+.
|
||||
final void Function(InAppWebViewController controller, String url,
|
||||
int statusCode, String description) onLoadHttpError;
|
||||
|
||||
///Event fired when the current [progress] of loading a page is changed.
|
||||
final void Function(InAppWebViewController controller, int progress)
|
||||
onProgressChanged;
|
||||
|
||||
///Event fired when the [WebView] receives a [ConsoleMessage].
|
||||
final void Function(
|
||||
InAppWebViewController controller, ConsoleMessage consoleMessage)
|
||||
onConsoleMessage;
|
||||
|
||||
///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. This event is not called on the initial load of the WebView.
|
||||
///
|
||||
///Note that on Android there isn't any way to load an URL for a frame that is not the main frame, so if the request is not for the main frame, the navigation is allowed by default.
|
||||
///However, if you want to cancel requests for subframes, you can use the [AndroidInAppWebViewOptions.regexToCancelSubFramesLoading] option
|
||||
///to write a Regular Expression that, if the url request of a subframe matches, then the request of that subframe is canceled.
|
||||
///
|
||||
///Also, on Android, this method is not called for POST requests.
|
||||
///
|
||||
///[shouldOverrideUrlLoadingRequest] represents the navigation request.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
|
||||
final Future<ShouldOverrideUrlLoadingAction> Function(
|
||||
InAppWebViewController controller,
|
||||
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest)
|
||||
shouldOverrideUrlLoading;
|
||||
|
||||
///Event fired when the [WebView] loads a resource.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnLoadResource] and [InAppWebViewOptions.javaScriptEnabled] options to `true`.
|
||||
final void Function(
|
||||
InAppWebViewController controller, LoadedResource resource)
|
||||
onLoadResource;
|
||||
|
||||
///Event fired when the [WebView] scrolls.
|
||||
///
|
||||
///[x] represents the current horizontal scroll origin in pixels.
|
||||
///
|
||||
///[y] represents the current vertical scroll origin in pixels.
|
||||
final void Function(InAppWebViewController controller, int x, int y)
|
||||
onScrollChanged;
|
||||
|
||||
///Event fired when [WebView] recognizes and starts a downloadable file.
|
||||
///
|
||||
///[url] represents the url of the file.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
|
||||
final void Function(InAppWebViewController controller, String url)
|
||||
onDownloadStart;
|
||||
|
||||
///Event fired when the [WebView] finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`.
|
||||
///
|
||||
///[scheme] represents the scheme of the url.
|
||||
///
|
||||
///[url] represents the url of the request.
|
||||
final Future<CustomSchemeResponse> Function(
|
||||
InAppWebViewController controller, String scheme, String url)
|
||||
onLoadResourceCustomScheme;
|
||||
|
||||
///Event fired when the [WebView] requests the host application to create a new window,
|
||||
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
|
||||
///
|
||||
///[onCreateWindowRequest] represents the request.
|
||||
///
|
||||
///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
|
||||
final void Function(InAppWebViewController controller,
|
||||
OnCreateWindowRequest onCreateWindowRequest) onCreateWindow;
|
||||
|
||||
///Event fired when javascript calls the `alert()` method to display an alert dialog.
|
||||
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
final Future<JsAlertResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsAlert;
|
||||
|
||||
///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
|
||||
///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
final Future<JsConfirmResponse> Function(
|
||||
InAppWebViewController controller, String message) onJsConfirm;
|
||||
|
||||
///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
|
||||
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///
|
||||
///[defaultValue] represents the default value displayed in the prompt dialog.
|
||||
final Future<JsPromptResponse> Function(InAppWebViewController controller,
|
||||
String message, String defaultValue) onJsPrompt;
|
||||
|
||||
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
|
||||
final Future<HttpAuthResponse> Function(
|
||||
InAppWebViewController controller, HttpAuthChallenge challenge)
|
||||
onReceivedHttpAuthRequest;
|
||||
|
||||
///Event fired when the WebView need to perform server trust authentication (certificate validation).
|
||||
///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED].
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge].
|
||||
final Future<ServerTrustAuthResponse> Function(
|
||||
InAppWebViewController controller, ServerTrustChallenge challenge)
|
||||
onReceivedServerTrustAuthRequest;
|
||||
|
||||
///Notify the host application to handle an SSL client certificate request.
|
||||
///Webview stores the response in memory (for the life of the application) if [ClientCertResponseAction.PROCEED] or [ClientCertResponseAction.CANCEL]
|
||||
///is called and does not call [onReceivedClientCertRequest] again for the same host and port pair.
|
||||
///Note that, multiple layers in chromium network stack might be caching the responses.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge].
|
||||
final Future<ClientCertResponse> Function(
|
||||
InAppWebViewController controller, ClientCertChallenge challenge)
|
||||
onReceivedClientCertRequest;
|
||||
|
||||
///Event fired as find-on-page operations progress.
|
||||
///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true.
|
||||
///
|
||||
///[activeMatchOrdinal] represents the zero-based ordinal of the currently selected match.
|
||||
///
|
||||
///[numberOfMatches] represents how many matches have been found.
|
||||
///
|
||||
///[isDoneCounting] whether the find operation has actually completed.
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting) onFindResultReceived;
|
||||
|
||||
///Event fired when an `XMLHttpRequest` is sent to a server.
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
///
|
||||
///[ajaxRequest] represents the `XMLHttpRequest`.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
|
||||
///Also, unlike iOS that has [WKUserScript](https://developer.apple.com/documentation/webkit/wkuserscript) that
|
||||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
|
||||
final Future<AjaxRequest> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
shouldInterceptAjaxRequest;
|
||||
|
||||
///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
|
||||
///It gives the host application a chance to abort the request.
|
||||
///
|
||||
///[ajaxRequest] represents the [XMLHttpRequest].
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
|
||||
///Also, unlike iOS that has [WKUserScript](https://developer.apple.com/documentation/webkit/wkuserscript) that
|
||||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
onAjaxReadyStateChange;
|
||||
|
||||
///Event fired as an `XMLHttpRequest` progress.
|
||||
///It gives the host application a chance to abort the request.
|
||||
///
|
||||
///[ajaxRequest] represents the [XMLHttpRequest].
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
|
||||
///Also, unlike iOS that has [WKUserScript](https://developer.apple.com/documentation/webkit/wkuserscript) that
|
||||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
onAjaxProgress;
|
||||
|
||||
///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API).
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
///
|
||||
///[fetchRequest] represents a resource request.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptFetchRequest] option to `true`.
|
||||
///Also, unlike iOS that has [WKUserScript](https://developer.apple.com/documentation/webkit/wkuserscript) that
|
||||
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
|
||||
///used to intercept fetch requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
|
||||
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the fetch requests will be intercept for sure.
|
||||
final Future<FetchRequest> Function(
|
||||
InAppWebViewController controller, FetchRequest fetchRequest)
|
||||
shouldInterceptFetchRequest;
|
||||
|
||||
///Event fired when the host application updates its visited links database.
|
||||
///This event is also fired when the navigation state of the [WebView] changes through the usage of
|
||||
///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event
|
||||
///or, also, when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url).
|
||||
///
|
||||
///[url] represents the url being visited.
|
||||
///
|
||||
///[androidIsReload] indicates if this url is being reloaded. Available only on Android.
|
||||
final void Function(
|
||||
InAppWebViewController controller, String url, bool androidIsReload)
|
||||
onUpdateVisitedHistory;
|
||||
|
||||
///Event fired when `window.print()` is called from JavaScript side.
|
||||
///
|
||||
///[url] represents the url on which is called.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
final void Function(InAppWebViewController controller, String url) onPrint;
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
///
|
||||
///[hitTestResult] represents the hit result for hitting an HTML elements.
|
||||
final void Function(InAppWebViewController controller,
|
||||
LongPressHitTestResult hitTestResult) onLongPressHitTestResult;
|
||||
|
||||
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
|
||||
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
|
||||
///
|
||||
///[url] represents the url of the request.
|
||||
///
|
||||
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
|
||||
///
|
||||
///**NOTE**: available only on Android 27+.
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat threatType) androidOnSafeBrowsingHit;
|
||||
|
||||
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
|
||||
///
|
||||
///[origin] represents the origin of the web page which is trying to access the restricted resources.
|
||||
///
|
||||
///[resources] represents the array of resources the web content wants to access.
|
||||
///
|
||||
///**NOTE**: available only on Android 23+.
|
||||
final Future<PermissionRequestResponse> Function(
|
||||
InAppWebViewController controller,
|
||||
String origin,
|
||||
List<String> resources) androidOnPermissionRequest;
|
||||
|
||||
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
|
||||
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
|
||||
///On non-secure origins geolocation requests are automatically denied.
|
||||
///
|
||||
///[origin] represents the origin of the web content attempting to use the Geolocation API.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(
|
||||
InAppWebViewController controller, String origin)
|
||||
androidOnGeolocationPermissionsShowPrompt;
|
||||
|
||||
///Notify the host application that a request for Geolocation permissions, made with a previous call to [androidOnGeolocationPermissionsShowPrompt] has been canceled.
|
||||
///Any related UI should therefore be hidden.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
||||
///Invoked when the web view's web content process is terminated.
|
||||
///
|
||||
///**NOTE**: available only on iOS.
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
iosOnWebContentProcessDidTerminate;
|
||||
|
||||
///Called when the web view begins to receive web content.
|
||||
///
|
||||
///**NOTE**: available only on iOS.
|
||||
final Future<void> Function(InAppWebViewController controller) iosOnDidCommit;
|
||||
|
||||
///Called when a web view receives a server redirect.
|
||||
///
|
||||
///**NOTE**: available only on iOS.
|
||||
final Future<void> Function(InAppWebViewController controller)
|
||||
iosOnDidReceiveServerRedirectForProvisionalNavigation;
|
||||
|
||||
///Initial url that will be loaded.
|
||||
final String initialUrl;
|
||||
|
||||
///Initial asset file that will be loaded. See [InAppWebViewController.loadFile] for explanation.
|
||||
final String initialFile;
|
||||
|
||||
///Initial [InAppWebViewInitialData] that will be loaded.
|
||||
final InAppWebViewInitialData initialData;
|
||||
|
||||
///Initial headers that will be used.
|
||||
final Map<String, String> initialHeaders;
|
||||
|
||||
///Initial options that will be used.
|
||||
final InAppWebViewGroupOptions initialOptions;
|
||||
|
||||
WebView(
|
||||
{this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
this.onLoadStop,
|
||||
this.onLoadError,
|
||||
this.onLoadHttpError,
|
||||
this.onProgressChanged,
|
||||
this.onConsoleMessage,
|
||||
this.shouldOverrideUrlLoading,
|
||||
this.onLoadResource,
|
||||
this.onScrollChanged,
|
||||
this.onDownloadStart,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onJsAlert,
|
||||
this.onJsConfirm,
|
||||
this.onJsPrompt,
|
||||
this.onReceivedHttpAuthRequest,
|
||||
this.onReceivedServerTrustAuthRequest,
|
||||
this.onReceivedClientCertRequest,
|
||||
this.onFindResultReceived,
|
||||
this.shouldInterceptAjaxRequest,
|
||||
this.onAjaxReadyStateChange,
|
||||
this.onAjaxProgress,
|
||||
this.shouldInterceptFetchRequest,
|
||||
this.onUpdateVisitedHistory,
|
||||
this.onPrint,
|
||||
this.onLongPressHitTestResult,
|
||||
this.androidOnSafeBrowsingHit,
|
||||
this.androidOnPermissionRequest,
|
||||
this.androidOnGeolocationPermissionsShowPrompt,
|
||||
this.androidOnGeolocationPermissionsHidePrompt,
|
||||
this.iosOnWebContentProcessDidTerminate,
|
||||
this.iosOnDidCommit,
|
||||
this.iosOnDidReceiveServerRedirectForProvisionalNavigation,
|
||||
this.initialUrl,
|
||||
this.initialFile,
|
||||
this.initialData,
|
||||
this.initialHeaders,
|
||||
this.initialOptions});
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_inappwebview
|
||||
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
|
||||
version: 3.0.0
|
||||
version: 3.1.0
|
||||
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||
|
||||
environment:
|
||||
|
|
Loading…
Reference in New Issue