added support for iOS inline native WebView integrated in the flutter widget tree (#18, #45), fix #54 #38 #26 #32 #33 #29 #15
This commit is contained in:
parent
2b600fbb6c
commit
1dfa6323c6
|
@ -16,7 +16,19 @@
|
|||
<component name="ChangeListManager">
|
||||
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/example/lib/main.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/main.dart" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/android/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/android/build.gradle" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties" beforeDir="false" afterPath="$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/example/android/gradle/wrapper/gradle-wrapper.properties" beforeDir="false" afterPath="$PROJECT_DIR$/example/android/gradle/wrapper/gradle-wrapper.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/example/lib/webview_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/webview_example.screen.dart" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/flutter_inappbrowser.iml" beforeDir="false" afterPath="$PROJECT_DIR$/flutter_inappbrowser.iml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
|
||||
</list>
|
||||
<ignored path="$PROJECT_DIR$/.dart_tool/" />
|
||||
<ignored path="$PROJECT_DIR$/.idea/" />
|
||||
|
@ -36,8 +48,8 @@
|
|||
<file leaf-file-name="flutter_inappbrowser.dart" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="4380">
|
||||
<caret line="323" column="41" selection-start-line="323" selection-start-column="41" selection-end-line="323" selection-end-column="41" />
|
||||
<state relative-caret-position="415">
|
||||
<caret line="698" column="22" selection-start-line="698" selection-start-column="13" selection-end-line="698" selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="e#814#831#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -45,13 +57,31 @@
|
|||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="main.dart" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
|
||||
<file leaf-file-name="CHANGELOG.md" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="405">
|
||||
<caret line="27" column="18" lean-forward="true" selection-start-line="27" selection-start-column="18" selection-end-line="27" selection-end-column="18" />
|
||||
<state relative-caret-position="195">
|
||||
<caret line="13" column="21" selection-start-line="13" selection-start-column="21" selection-end-line="13" selection-end-column="21" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="pubspec.yaml" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="195">
|
||||
<caret line="13" column="14" lean-forward="true" selection-start-line="13" selection-start-column="14" selection-end-line="13" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="README.md" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/README.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="589">
|
||||
<caret line="72" column="7" lean-forward="true" selection-start-line="72" selection-start-column="7" selection-end-line="72" selection-end-column="7" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
<element signature="e#0#39#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
|
@ -68,20 +98,6 @@
|
|||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>assert(</find>
|
||||
<find>sNotEmpty()</find>
|
||||
<find>loadData</find>
|
||||
<find>_valide</find>
|
||||
<find>initialized</find>
|
||||
<find>HashMap</find>
|
||||
<find>headers</find>
|
||||
<find>.cast</find>
|
||||
<find>WebView</find>
|
||||
<find>print</find>
|
||||
<find>throw</find>
|
||||
<find>InAppWeb</find>
|
||||
<find>Boolean</find>
|
||||
<find>[WebHistory.list]</find>
|
||||
<find>open</find>
|
||||
<find>Cannot laod</find>
|
||||
<find>_throwIsNotOpened</find>
|
||||
|
@ -98,6 +114,20 @@
|
|||
<find>initialData</find>
|
||||
<find>openData</find>
|
||||
<find>optionsType</find>
|
||||
<find>InAppWebView</find>
|
||||
<find>fromInAppBrowser</find>
|
||||
<find>InAppWebViewController</find>
|
||||
<find>_handleMethod</find>
|
||||
<find>InAppBrowser</find>
|
||||
<find>handlerTest</find>
|
||||
<find>onLoadStart</find>
|
||||
<find>distributionUrl</find>
|
||||
<find>args.putIfAbsent('isData', () => false);</find>
|
||||
<find>VERSIONING_SYSTEM</find>
|
||||
<find>config.build_settings['SWIFT_VERSION']</find>
|
||||
<find>BUILD TARGET</find>
|
||||
<find>InAppWebView {</find>
|
||||
<find>AndroidView</find>
|
||||
</findStrings>
|
||||
<replaceStrings>
|
||||
<replace>activity.getPreferences(0)</replace>
|
||||
|
@ -132,26 +162,29 @@
|
|||
<option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java" />
|
||||
<option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" />
|
||||
<option value="$PROJECT_DIR$/example/ios/Podfile" />
|
||||
<option value="$PROJECT_DIR$/android/build.gradle" />
|
||||
<option value="$PROJECT_DIR$/example/html/css/style.css" />
|
||||
<option value="$PROJECT_DIR$/example/html/index.html" />
|
||||
<option value="$PROJECT_DIR$/example/assets/css/style.css" />
|
||||
<option value="$PROJECT_DIR$/example/assets/index.html" />
|
||||
<option value="$PROJECT_DIR$/example/ios/Flutter/Generated.xcconfig" />
|
||||
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
|
||||
<option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" />
|
||||
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
|
||||
<option value="$PROJECT_DIR$/example/lib/webview_example.screen.dart" />
|
||||
<option value="$PROJECT_DIR$/example/lib/test.dart" />
|
||||
<option value="$PROJECT_DIR$/example/lib/main.dart" />
|
||||
<option value="$PROJECT_DIR$/android/build.gradle" />
|
||||
<option value="$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties" />
|
||||
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
||||
<option value="$PROJECT_DIR$/README.md" />
|
||||
<option value="$PROJECT_DIR$/pubspec.yaml" />
|
||||
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
||||
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
|
||||
<option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" />
|
||||
<option value="$PROJECT_DIR$/example/lib/main.dart" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="y" value="23" />
|
||||
<option name="width" value="1641" />
|
||||
<option name="height" value="1027" />
|
||||
<option name="width" value="1920" />
|
||||
<option name="height" value="1057" />
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectView">
|
||||
|
@ -159,7 +192,35 @@
|
|||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="AndroidView" />
|
||||
<pane id="AndroidView">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="1abcf292:AndroidViewProjectNode" />
|
||||
<item name="flutter_inappbrowser_android" type="e9137016:NonAndroidModuleNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="1abcf292:AndroidViewProjectNode" />
|
||||
<item name="flutter_inappbrowser_android" type="e9137016:NonAndroidModuleNode" />
|
||||
<item name="java" type="f7eae187:NonAndroidSourceTypeNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="1abcf292:AndroidViewProjectNode" />
|
||||
<item name="flutter_inappbrowser_android" type="e9137016:NonAndroidModuleNode" />
|
||||
<item name="java" type="f7eae187:NonAndroidSourceTypeNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="1abcf292:AndroidViewProjectNode" />
|
||||
<item name="flutter_inappbrowser_android" type="e9137016:NonAndroidModuleNode" />
|
||||
<item name="java" type="f7eae187:NonAndroidSourceTypeNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="InAppWebView" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope">
|
||||
<subPane subId="Project Files">
|
||||
<expand>
|
||||
|
@ -178,29 +239,6 @@
|
|||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="ios" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="ios" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="Runner" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="ios" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
|
@ -368,33 +406,33 @@
|
|||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="23" width="1680" height="1027" extended-state="6" />
|
||||
<frame x="0" y="23" width="1920" height="1057" extended-state="0" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="TODO" order="6" />
|
||||
<window_info anchor="bottom" id="Messages" order="12" weight="0.23585913" />
|
||||
<window_info anchor="right" id="Palette	" order="9" />
|
||||
<window_info id="Image Layers" order="7" />
|
||||
<window_info id="Build Variants" order="3" side_tool="true" />
|
||||
<window_info anchor="right" id="Capture Analysis" order="4" />
|
||||
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.5052169" side_tool="true" weight="0.34068358" />
|
||||
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.32745314" />
|
||||
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49478307" weight="0.29437706" />
|
||||
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49478307" visible="true" weight="0.36926362" />
|
||||
<window_info anchor="bottom" id="Version Control" order="9" />
|
||||
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.49533224" visible="true" weight="0.24696803" />
|
||||
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.49533224" weight="0.24653149" />
|
||||
<window_info anchor="right" id="Flutter Outline" order="6" weight="0.32922077" />
|
||||
<window_info anchor="bottom" id="Logcat" order="11" />
|
||||
<window_info id="Captures" order="4" weight="0.32936507" />
|
||||
<window_info id="Capture Tool" order="6" />
|
||||
<window_info id="Designer" order="2" />
|
||||
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.49341142" visible="true" weight="0.13125764" />
|
||||
<window_info id="Structure" order="1" sideWeight="0.5065886" side_tool="true" visible="true" weight="0.13125764" />
|
||||
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.6615905" visible="true" weight="0.18210863" />
|
||||
<window_info id="Structure" order="1" sideWeight="0.33840948" side_tool="true" visible="true" weight="0.18210863" />
|
||||
<window_info anchor="right" id="Device File Explorer" order="5" side_tool="true" />
|
||||
<window_info anchor="right" id="Theme Preview" order="7" />
|
||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.34288865" />
|
||||
<window_info id="Favorites" order="5" side_tool="true" />
|
||||
<window_info anchor="right" id="Flutter Inspector" order="3" weight="0.32938388" />
|
||||
<window_info anchor="bottom" id="Messages" order="12" visible="true" weight="0.23594266" />
|
||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
|
||||
<window_info anchor="right" id="Assistant" order="8" visible="true" weight="0.3295129" />
|
||||
|
@ -418,55 +456,6 @@
|
|||
</breakpoint-manager>
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppBrowser.h" />
|
||||
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppBrowser.m" />
|
||||
<entry file="file://$PROJECT_DIR$/LICENSE">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="15">
|
||||
<caret line="1" column="31" selection-start-line="1" selection-start-column="31" selection-end-line="1" selection-end-column="31" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/src/main/AndroidManifest.xml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="90">
|
||||
<caret line="6" lean-forward="true" selection-start-line="6" selection-end-line="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserClient.java" />
|
||||
<entry file="file://$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserDialog.java" />
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/Release.xcconfig">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/Debug.xcconfig">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="30">
|
||||
<caret line="2" selection-start-line="2" selection-end-line="2" selection-end-column="24" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="180">
|
||||
<caret line="12" selection-start-line="12" selection-end-line="12" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="191">
|
||||
<caret line="107" column="9" selection-start-line="107" selection-start-column="9" selection-end-line="107" selection-end-column="9" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/android/build.gradle">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
|
@ -510,23 +499,6 @@
|
|||
<state relative-caret-position="-10645" />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/settings.gradle">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<caret column="20" selection-start-column="20" selection-end-column="20" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/local.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/gradle.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib/core/string.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="173">
|
||||
|
@ -534,20 +506,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/ios/flutter_inappbrowser.podspec">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="330">
|
||||
<caret line="22" lean-forward="true" selection-start-line="22" selection-end-line="22" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/build.gradle">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="414">
|
||||
<caret line="34" column="5" selection-start-line="34" selection-start-column="5" selection-end-line="34" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/assets/images/dart.svg">
|
||||
<provider selected="true" editor-type-id="images">
|
||||
<state />
|
||||
|
@ -572,13 +530,6 @@
|
|||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Podfile">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="975">
|
||||
<caret line="65" column="52" selection-start-line="65" selection-start-column="52" selection-end-line="65" selection-end-column="52" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/flutter_webview_example.iml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
|
@ -643,54 +594,178 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||
<entry file="file://$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="15">
|
||||
<caret line="1" column="103" selection-start-line="1" selection-start-column="103" selection-end-line="1" selection-end-column="103" />
|
||||
<state relative-caret-position="-1555">
|
||||
<caret line="2" selection-start-line="2" selection-end-line="2" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||
<entry file="file://$PROJECT_DIR$/ios/flutter_inappbrowser.podspec">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<caret selection-end-line="3" selection-end-column="21" />
|
||||
<state relative-caret-position="330">
|
||||
<caret line="22" selection-start-line="22" selection-end-line="22" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/README.md">
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="327">
|
||||
<caret line="601" column="21" selection-start-line="601" selection-start-column="21" selection-end-line="601" selection-end-column="21" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Runner/Info.plist">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="735">
|
||||
<caret line="49" column="4" selection-start-line="49" selection-start-column="4" selection-end-line="49" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="4380">
|
||||
<caret line="323" column="41" selection-start-line="323" selection-start-column="41" selection-end-line="323" selection-end-column="41" />
|
||||
<state relative-caret-position="52">
|
||||
<caret line="14" column="20" selection-start-line="14" selection-start-column="20" selection-end-line="14" selection-end-column="20" />
|
||||
<folding>
|
||||
<element signature="e#814#831#0" expanded="true" />
|
||||
<element signature="e#0#39#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/webview_example.screen.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="254">
|
||||
<caret line="63" column="2" selection-start-line="63" selection-start-column="2" selection-end-line="63" selection-end-column="2" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="405">
|
||||
<caret line="27" column="18" lean-forward="true" selection-start-line="27" selection-start-column="18" selection-end-line="27" selection-end-column="18" />
|
||||
<state relative-caret-position="24">
|
||||
<caret line="27" column="18" selection-end-line="63" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/test.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="590">
|
||||
<caret line="475" selection-start-line="343" selection-end-line="475" />
|
||||
<folding>
|
||||
<element signature="e#0#16428#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/gradle.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/local.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/android/gradle/wrapper/gradle-wrapper.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="75">
|
||||
<caret line="5" selection-start-line="5" selection-end-line="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/settings.gradle">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="15">
|
||||
<caret line="1" selection-start-line="1" selection-end-line="1" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="75">
|
||||
<caret line="5" selection-start-line="5" selection-end-line="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/chrome_safari_example.screen.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="317">
|
||||
<caret line="24" column="80" selection-start-line="24" selection-start-column="68" selection-end-line="24" selection-end-column="80" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/android/build.gradle">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="110">
|
||||
<caret line="10" column="55" selection-start-line="10" selection-start-column="55" selection-end-line="10" selection-end-column="55" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/App.framework/Info.plist">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/Flutter.framework/Info.plist">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/AppFrameworkInfo.plist">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Runner/Info.plist">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="511">
|
||||
<caret line="49" column="4" selection-start-line="49" selection-start-column="4" selection-end-line="49" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="211">
|
||||
<caret line="453" column="10" selection-start-line="453" selection-start-column="10" selection-end-line="453" selection-end-column="10" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/ios/Podfile">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="614">
|
||||
<caret line="66" column="44" selection-start-line="66" selection-start-column="6" selection-end-line="66" selection-end-column="44" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="415">
|
||||
<caret line="698" column="22" selection-start-line="698" selection-start-column="13" selection-end-line="698" selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="e#814#831#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/README.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="589">
|
||||
<caret line="72" column="7" lean-forward="true" selection-start-line="72" selection-start-column="7" selection-end-line="72" selection-end-column="7" />
|
||||
<folding>
|
||||
<element signature="e#0#39#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="195">
|
||||
<caret line="13" column="21" selection-start-line="13" selection-start-column="21" selection-end-line="13" selection-end-column="21" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="195">
|
||||
<caret line="13" column="14" lean-forward="true" selection-start-line="13" selection-start-column="14" selection-end-line="13" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
|||
## 0.6.0
|
||||
|
||||
- added support for **iOS** inline native WebView integrated in the flutter widget tree
|
||||
- updated example folder (thanks to [marquesinijatinha](https://github.com/marquesinijatinha))
|
||||
- Fixed bug where passing null to expiresDate failed (thanks to [Sense545](https://github.com/Sense545))
|
||||
- Fixed iOS error: encode resourceURL (thanks to [igtm](https://github.com/igtm))
|
||||
- Fixed iOS error: Double value cannot be converted to Int because the result would be greater than Int.max in 32-bit devices (thanks to [huzhiren](https://github.com/huzhiren))
|
||||
- Fixed iOS error: problem in ChromeSafariBrowser (thanks to [marquesinijatinha](https://github.com/marquesinijatinha))
|
||||
- Fixed Android build error caused by gradle and build gradle versions (thanks to [tje3d](https://github.com/tje3d))
|
||||
|
||||
## 0.5.51
|
||||
|
||||
- updated `pubspec.yaml`
|
||||
|
|
33
README.md
33
README.md
|
@ -15,12 +15,30 @@ This plugin is inspired by the popular [cordova-plugin-inappbrowser](https://git
|
|||
- Flutter: ">=0.10.1 <2.0.0"
|
||||
|
||||
### IMPORTANT Note for iOS
|
||||
To be able to use this plugin on iOS, you need to create the Flutter App with `flutter create -i swift` (see [flutter/flutter#13422 (comment)](https://github.com/flutter/flutter/issues/13422#issuecomment-392133780)), otherwise, you will get this message:
|
||||
If you are starting a new fresh app, you need to create the Flutter App with `flutter create -i swift` (see [flutter/flutter#13422 (comment)](https://github.com/flutter/flutter/issues/13422#issuecomment-392133780)), otherwise, you will get this message:
|
||||
```
|
||||
=== BUILD TARGET flutter_inappbrowser OF PROJECT Pods WITH CONFIGURATION Debug ===
|
||||
The “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift. Supported values are: 3.0, 4.0, 4.2. This setting can be set in the build settings editor.
|
||||
```
|
||||
that is not true! The Swift version that I have used is already a supported value: 4.0.
|
||||
|
||||
If you still have this problem, try to edit iOS `Podfile` like this (see [#15](https://github.com/pichillilorenzo/flutter_inappbrowser/issues/15)):
|
||||
```
|
||||
target 'Runner' do
|
||||
use_frameworks! # required by simple_permission
|
||||
...
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['SWIFT_VERSION'] = '4.0' # required by simple_permission
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Instead, if you have already a non-swift project, you can check this issue to solve the problem: [Friction adding swift plugin to objective-c project](https://github.com/flutter/flutter/issues/16049).
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
@ -34,7 +52,7 @@ First, add `flutter_inappbrowser` as a [dependency in your pubspec.yaml file](ht
|
|||
|
||||
## Usage
|
||||
Classes:
|
||||
- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree. [**Available only for Android** ([AndroidView](https://docs.flutter.io/flutter/widgets/AndroidView-class.html)) at this moment. For iOS, it will be available as soon as the Flutter team will release the corresponding dart class.].
|
||||
- [InAppWebView](#inappwebview-class): Flutter Widget for adding an **inline native WebView** integrated in 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`.
|
||||
- [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`.
|
||||
|
@ -45,11 +63,10 @@ See the online [docs](https://pub.dartlang.org/documentation/flutter_inappbrowse
|
|||
### `InAppWebView` class
|
||||
Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
|
||||
|
||||
[AndroidView](https://docs.flutter.io/flutter/widgets/AndroidView-class.html) is not officially stable yet!
|
||||
[AndroidView](https://docs.flutter.io/flutter/widgets/AndroidView-class.html) and [UiKitView](https://docs.flutter.io/flutter/widgets/UiKitView-class.html) is not officially stable yet!
|
||||
So, if you want use it, you can but you will have some limitation such as the inability to use the keyboard!
|
||||
|
||||
**Available only for Android** ([AndroidView](https://docs.flutter.io/flutter/widgets/AndroidView-class.html)) at this moment.
|
||||
For iOS, it will be available as soon as the Flutter team will release the corresponding dart class.
|
||||
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`.
|
||||
|
||||
Use `InAppWebViewController` to control the WebView instance.
|
||||
Example:
|
||||
|
@ -189,6 +206,10 @@ Screenshots:
|
|||
|
||||
![android](https://user-images.githubusercontent.com/5956938/47271038-7aebda80-d574-11e8-98fd-41e6bbc9fe2d.gif)
|
||||
|
||||
- iOS:
|
||||
|
||||
![ios](https://user-images.githubusercontent.com/5956938/54096363-e1e72000-43ab-11e9-85c2-983a830ab7a0.gif)
|
||||
|
||||
#### InAppWebView.initialUrl
|
||||
Initial url that will be loaded.
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.2'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -359,14 +359,15 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
|
||||
getChannel().invokeMethod("onLoadResource", obj);
|
||||
|
||||
return new WebResourceResponse(
|
||||
response.header("content-type", "text/plain").split(";")[0].trim(),
|
||||
response.header("content-encoding"),
|
||||
response.code(),
|
||||
reasonPhrase,
|
||||
headersResponse,
|
||||
dataStream
|
||||
);
|
||||
// this return is not working (it blocks some resources), so return null
|
||||
// return new WebResourceResponse(
|
||||
// response.header("content-type", "text/plain").split(";")[0].trim(),
|
||||
// response.header("content-encoding", "utf-8"),
|
||||
// response.code(),
|
||||
// reasonPhrase,
|
||||
// headersResponse,
|
||||
// dataStream
|
||||
// );
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.d(LOG_TAG, e.getMessage());
|
||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
||||
|
|
|
@ -446,7 +446,7 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = On;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
|
@ -474,7 +474,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutter_inappbrowserExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = On;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
|
|
|
@ -4,7 +4,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_inappbrowser/flutter_inappbrowser.dart';
|
||||
|
||||
class MyInappBrowser extends InAppBrowser {
|
||||
@override
|
||||
|
||||
@override
|
||||
Future onBrowserCreated() async {
|
||||
print("\n\nBrowser Ready!\n\n");
|
||||
}
|
||||
|
@ -64,7 +65,7 @@ class MyInappBrowser extends InAppBrowser {
|
|||
}
|
||||
|
||||
class WebviewExampleScreen extends StatefulWidget {
|
||||
final InAppBrowser browser = new InAppBrowser();
|
||||
final InAppBrowser browser = new MyInappBrowser();
|
||||
@override
|
||||
_WebviewExampleScreenState createState() => new _WebviewExampleScreenState();
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/ios/Flutter/flutter_assets/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/flutter_assets/packages" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
|
|
@ -14,73 +14,6 @@ import AVFoundation
|
|||
typealias OlderClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
|
||||
typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
|
||||
|
||||
// the message needs to be concatenated with '' in order to have the same behavior like on Android
|
||||
let consoleLogJS = """
|
||||
(function() {
|
||||
var oldLogs = {
|
||||
'consoleLog': console.log,
|
||||
'consoleDebug': console.debug,
|
||||
'consoleError': console.error,
|
||||
'consoleInfo': console.info,
|
||||
'consoleWarn': console.warn
|
||||
};
|
||||
|
||||
for (var k in oldLogs) {
|
||||
(function(oldLog) {
|
||||
console[oldLog.replace('console', '').toLowerCase()] = function() {
|
||||
var message = '';
|
||||
for (var i in arguments) {
|
||||
if (message == '') {
|
||||
message += arguments[i];
|
||||
}
|
||||
else {
|
||||
message += ' ' + arguments[i];
|
||||
}
|
||||
}
|
||||
window.webkit.messageHandlers[oldLog].postMessage(message);
|
||||
}
|
||||
})(k);
|
||||
}
|
||||
})();
|
||||
"""
|
||||
|
||||
let resourceObserverJS = """
|
||||
(function() {
|
||||
var observer = new PerformanceObserver(function(list) {
|
||||
list.getEntries().forEach(function(entry) {
|
||||
window.webkit.messageHandlers['resourceLoaded'].postMessage(JSON.stringify(entry));
|
||||
});
|
||||
});
|
||||
observer.observe({entryTypes: ['resource', 'mark', 'measure']});
|
||||
})();
|
||||
"""
|
||||
|
||||
let JAVASCRIPT_BRIDGE_NAME = "flutter_inappbrowser"
|
||||
|
||||
let javaScriptBridgeJS = """
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME) = {};
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function(handlerName, ...args) {
|
||||
window.webkit.messageHandlers['callHandler'].postMessage( {'handlerName': handlerName, 'args': JSON.stringify(args)} );
|
||||
}
|
||||
"""
|
||||
|
||||
func currentTimeInMilliSeconds() -> Int64 {
|
||||
let currentDate = Date()
|
||||
let since1970 = currentDate.timeIntervalSince1970
|
||||
return Int64(since1970 * 1000)
|
||||
}
|
||||
|
||||
func convertToDictionary(text: String) -> [String: Any]? {
|
||||
if let data = text.data(using: .utf8) {
|
||||
do {
|
||||
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//extension WKWebView{
|
||||
//
|
||||
// var keyboardDisplayRequiresUserAction: Bool? {
|
||||
|
@ -137,7 +70,7 @@ class InAppWebView_IBWrapper: InAppWebView {
|
|||
}
|
||||
}
|
||||
|
||||
class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, UITextFieldDelegate, WKScriptMessageHandler {
|
||||
class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKUIDelegate, UITextFieldDelegate {
|
||||
|
||||
@IBOutlet var webView: InAppWebView_IBWrapper!
|
||||
@IBOutlet var closeButton: UIButton!
|
||||
|
@ -156,7 +89,7 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
@IBOutlet var webView_TopFullScreenConstraint: NSLayoutConstraint!
|
||||
|
||||
weak var navigationDelegate: SwiftFlutterPlugin?
|
||||
var currentURL: URL?
|
||||
var initURL: URL?
|
||||
var tmpWindow: UIWindow?
|
||||
var browserOptions: InAppBrowserOptions?
|
||||
var webViewOptions: InAppWebViewOptions?
|
||||
|
@ -189,12 +122,12 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
webView.uiDelegate = self
|
||||
webView.navigationDelegate = self
|
||||
webView.scrollView.delegate = self
|
||||
// webView.uiDelegate = self
|
||||
// webView.navigationDelegate = nil
|
||||
// webView.scrollView.delegate = self
|
||||
|
||||
urlField.delegate = self
|
||||
urlField.text = self.currentURL?.absoluteString
|
||||
urlField.text = self.initURL?.absoluteString
|
||||
|
||||
closeButton.addTarget(self, action: #selector(self.close), for: .touchUpInside)
|
||||
|
||||
|
@ -218,7 +151,7 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
spinner.stopAnimating()
|
||||
|
||||
if self.initData == nil {
|
||||
loadUrl(url: self.currentURL!, headers: self.initHeaders)
|
||||
loadUrl(url: self.initURL!, headers: self.initHeaders)
|
||||
}
|
||||
else {
|
||||
loadData(data: initData!, mimeType: initMimeType!, encoding: initEncoding!, baseUrl: initBaseUrl!)
|
||||
|
@ -245,13 +178,8 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
func prepareWebView() {
|
||||
//UIApplication.shared.statusBarStyle = preferredStatusBarStyle
|
||||
|
||||
self.webView.addObserver(self,
|
||||
forKeyPath: #keyPath(WKWebView.estimatedProgress),
|
||||
options: .new,
|
||||
context: nil)
|
||||
|
||||
self.webView.configuration.userContentController = WKUserContentController()
|
||||
self.webView.configuration.preferences = WKPreferences()
|
||||
self.webView.options = webViewOptions
|
||||
self.webView.prepare()
|
||||
|
||||
if (browserOptions?.hideUrlBar)! {
|
||||
self.urlField.isHidden = true
|
||||
|
@ -290,133 +218,21 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
|
||||
self.modalPresentationStyle = UIModalPresentationStyle(rawValue: (browserOptions?.presentationStyle)!)!
|
||||
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (browserOptions?.transitionStyle)!)!
|
||||
|
||||
// prevent webView from bouncing
|
||||
if (webViewOptions?.disallowOverScroll)! {
|
||||
if self.webView.responds(to: #selector(getter: self.webView.scrollView)) {
|
||||
self.webView.scrollView.bounces = false
|
||||
}
|
||||
else {
|
||||
for subview: UIView in self.webView.subviews {
|
||||
if subview is UIScrollView {
|
||||
(subview as! UIScrollView).bounces = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (webViewOptions?.enableViewportScale)! {
|
||||
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
|
||||
let userScript = WKUserScript(source: jscript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
|
||||
self.webView.configuration.userContentController.addUserScript(userScript)
|
||||
}
|
||||
|
||||
// Prevents long press on links that cause WKWebView exit
|
||||
let jscriptWebkitTouchCallout = WKUserScript(source: "document.body.style.webkitTouchCallout='none';", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
|
||||
self.webView.configuration.userContentController.addUserScript(jscriptWebkitTouchCallout)
|
||||
|
||||
|
||||
let consoleLogJSScript = WKUserScript(source: consoleLogJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
self.webView.configuration.userContentController.addUserScript(consoleLogJSScript)
|
||||
self.webView.configuration.userContentController.add(self, name: "consoleLog")
|
||||
self.webView.configuration.userContentController.add(self, name: "consoleDebug")
|
||||
self.webView.configuration.userContentController.add(self, name: "consoleError")
|
||||
self.webView.configuration.userContentController.add(self, name: "consoleInfo")
|
||||
self.webView.configuration.userContentController.add(self, name: "consoleWarn")
|
||||
|
||||
let javaScriptBridgeJSScript = WKUserScript(source: javaScriptBridgeJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
self.webView.configuration.userContentController.addUserScript(javaScriptBridgeJSScript)
|
||||
self.webView.configuration.userContentController.add(self, name: "callHandler")
|
||||
|
||||
let resourceObserverJSScript = WKUserScript(source: resourceObserverJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
self.webView.configuration.userContentController.addUserScript(resourceObserverJSScript)
|
||||
self.webView.configuration.userContentController.add(self, name: "resourceLoaded")
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
self.webView.configuration.mediaTypesRequiringUserActionForPlayback = ((webViewOptions?.mediaPlaybackRequiresUserGesture)!) ? .all : []
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
self.webView.configuration.mediaPlaybackRequiresUserAction = (webViewOptions?.mediaPlaybackRequiresUserGesture)!
|
||||
}
|
||||
|
||||
|
||||
self.webView.configuration.allowsInlineMediaPlayback = (webViewOptions?.allowsInlineMediaPlayback)!
|
||||
|
||||
//self.webView.keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction
|
||||
|
||||
self.webView.configuration.suppressesIncrementalRendering = (webViewOptions?.suppressesIncrementalRendering)!
|
||||
self.webView.allowsBackForwardNavigationGestures = (webViewOptions?.allowsBackForwardNavigationGestures)!
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.allowsLinkPreview = (webViewOptions?.allowsLinkPreview)!
|
||||
}
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
self.webView.configuration.ignoresViewportScaleLimits = (webViewOptions?.ignoresViewportScaleLimits)!
|
||||
}
|
||||
|
||||
self.webView.configuration.allowsInlineMediaPlayback = (webViewOptions?.allowsInlineMediaPlayback)!
|
||||
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.configuration.allowsPictureInPictureMediaPlayback = (webViewOptions?.allowsPictureInPictureMediaPlayback)!
|
||||
}
|
||||
|
||||
self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = (webViewOptions?.javaScriptCanOpenWindowsAutomatically)!
|
||||
|
||||
self.webView.configuration.preferences.javaScriptEnabled = (webViewOptions?.javaScriptEnabled)!
|
||||
|
||||
if ((webViewOptions?.userAgent)! != "") {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.customUserAgent = (webViewOptions?.userAgent)!
|
||||
}
|
||||
}
|
||||
|
||||
if (webViewOptions?.clearCache)! {
|
||||
clearCache()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func loadUrl(url: URL, headers: [String: String]?) {
|
||||
var request = URLRequest(url: url)
|
||||
currentURL = url
|
||||
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
|
||||
if let mutableRequest = (request as NSURLRequest).mutableCopy() as? NSMutableURLRequest {
|
||||
for (key, value) in headers! {
|
||||
mutableRequest.setValue(value, forHTTPHeaderField: key)
|
||||
}
|
||||
request = mutableRequest as URLRequest
|
||||
}
|
||||
|
||||
webView.load(request)
|
||||
webView.loadUrl(url: url, headers: headers)
|
||||
updateUrlTextField(url: (webView.currentURL?.absoluteString)!)
|
||||
}
|
||||
|
||||
func loadData(data: String, mimeType: String, encoding: String, baseUrl: String) {
|
||||
let url = URL(string: baseUrl)!
|
||||
currentURL = url
|
||||
if #available(iOS 9.0, *) {
|
||||
webView.load(data.data(using: .utf8)!, mimeType: mimeType, characterEncodingName: encoding, baseURL: url)
|
||||
} else {
|
||||
webView.loadHTMLString(data, baseURL: url)
|
||||
}
|
||||
webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
|
||||
}
|
||||
|
||||
func postUrl(url: URL, postData: Data, result: @escaping FlutterResult) {
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.httpBody = postData
|
||||
|
||||
let task = URLSession.shared.dataTask(with: request) { (data : Data?, response : URLResponse?, error : Error?) in
|
||||
var returnString = ""
|
||||
if data != nil {
|
||||
returnString = String(data: data!, encoding: .utf8) ?? ""
|
||||
}
|
||||
DispatchQueue.main.async(execute: {() -> Void in
|
||||
self.webView.loadHTMLString(returnString, baseURL: url)
|
||||
result(true)
|
||||
})
|
||||
}
|
||||
task.resume()
|
||||
webView.postUrl(url: url, postData: postData, completionHandler: { () -> Void in
|
||||
result(true)
|
||||
})
|
||||
}
|
||||
|
||||
// Load user requested url
|
||||
|
@ -428,9 +244,8 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
webView.load(request)
|
||||
}
|
||||
else {
|
||||
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
updateUrlTextField(url: (webView.currentURL?.absoluteString)!)
|
||||
}
|
||||
//var list : WKBackForwardList = self.webView.backForwardList
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -439,30 +254,12 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
webView.frame = frame
|
||||
}
|
||||
|
||||
func clearCache() {
|
||||
if #available(iOS 9.0, *) {
|
||||
//let websiteDataTypes = NSSet(array: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
|
||||
let date = NSDate(timeIntervalSince1970: 0)
|
||||
WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), modifiedSince: date as Date, completionHandler:{ })
|
||||
} else {
|
||||
var libraryPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, false).first!
|
||||
libraryPath += "/Cookies"
|
||||
|
||||
do {
|
||||
try FileManager.default.removeItem(atPath: libraryPath)
|
||||
} catch {
|
||||
print("can't clear cache")
|
||||
}
|
||||
URLCache.shared.removeAllCachedResponses()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func reload () {
|
||||
webView.reload()
|
||||
}
|
||||
|
||||
@objc func share () {
|
||||
let vc = UIActivityViewController(activityItems: [currentURL ?? ""], applicationActivities: [])
|
||||
let vc = UIActivityViewController(activityItems: [webView.currentURL ?? ""], applicationActivities: [])
|
||||
present(vc, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
|
@ -569,237 +366,12 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
scanner.scanHexInt32(&hexInt)
|
||||
return hexInt
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView,
|
||||
decidePolicyFor navigationAction: WKNavigationAction,
|
||||
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
||||
|
||||
if let url = navigationAction.request.url {
|
||||
|
||||
if url.absoluteString != self.currentURL?.absoluteString && (webViewOptions?.useOnLoadResource)! {
|
||||
WKNavigationMap[url.absoluteString] = [
|
||||
"startTime": currentTimeInMilliSeconds(),
|
||||
"request": navigationAction.request
|
||||
]
|
||||
}
|
||||
|
||||
if navigationAction.navigationType == .linkActivated && (webViewOptions?.useShouldOverrideUrlLoading)! {
|
||||
if navigationDelegate != nil {
|
||||
navigationDelegate?.shouldOverrideUrlLoading(uuid: self.uuid, webView: webView, url: url)
|
||||
}
|
||||
decisionHandler(.cancel)
|
||||
return
|
||||
}
|
||||
|
||||
if navigationAction.navigationType == .linkActivated || navigationAction.navigationType == .backForward {
|
||||
currentURL = url
|
||||
updateUrlTextField(url: (url.absoluteString))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
decisionHandler(.allow)
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView,
|
||||
decidePolicyFor navigationResponse: WKNavigationResponse,
|
||||
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
|
||||
|
||||
if (webViewOptions?.useOnLoadResource)! {
|
||||
if let url = navigationResponse.response.url {
|
||||
if WKNavigationMap[url.absoluteString] != nil {
|
||||
let startResourceTime: Int64 = (WKNavigationMap[url.absoluteString]!["startTime"] as! Int64)
|
||||
let startTime: Int64 = startResourceTime - startPageTime;
|
||||
let duration: Int64 = currentTimeInMilliSeconds() - startResourceTime;
|
||||
self.didReceiveResourceResponse(navigationResponse.response, fromRequest: WKNavigationMap[url.absoluteString]!["request"] as? URLRequest, withData: Data(), startTime: startTime, duration: duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decisionHandler(.allow)
|
||||
}
|
||||
|
||||
// func webView(_ webView: WKWebView,
|
||||
// decidePolicyFor navigationResponse: WKNavigationResponse,
|
||||
// decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
|
||||
// let mimeType = navigationResponse.response.mimeType
|
||||
// if mimeType != nil && !mimeType!.starts(with: "text/") {
|
||||
// download(url: webView.url)
|
||||
// decisionHandler(.cancel)
|
||||
// return
|
||||
// }
|
||||
// decisionHandler(.allow)
|
||||
// }
|
||||
//
|
||||
// func download (url: URL?) {
|
||||
// let filename = url?.lastPathComponent
|
||||
//
|
||||
// let destination: DownloadRequest.DownloadFileDestination = { _, _ in
|
||||
// let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||
// let fileURL = documentsURL.appendingPathComponent(filename!)
|
||||
//
|
||||
// return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
|
||||
// }
|
||||
//
|
||||
// Alamofire.download((url?.absoluteString)!, to: destination).downloadProgress { progress in
|
||||
// print("Download Progress: \(progress.fractionCompleted)")
|
||||
// }.response { response in
|
||||
// if response.error == nil, let path = response.destinationURL?.path {
|
||||
// UIAlertView(title: nil, message: "File saved to " + path, delegate: nil, cancelButtonTitle: nil).show()
|
||||
// }
|
||||
// else {
|
||||
// UIAlertView(title: nil, message: "Cannot save " + filename!, delegate: nil, cancelButtonTitle: nil).show()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
||||
|
||||
self.startPageTime = currentTimeInMilliSeconds()
|
||||
|
||||
// loading url, start spinner, update back/forward
|
||||
backButton.isEnabled = webView.canGoBack
|
||||
forwardButton.isEnabled = webView.canGoForward
|
||||
|
||||
if (browserOptions?.spinner)! {
|
||||
spinner.startAnimating()
|
||||
}
|
||||
|
||||
if navigationDelegate != nil {
|
||||
navigationDelegate?.onLoadStart(uuid: self.uuid, webView: webView)
|
||||
}
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
self.WKNavigationMap = [:]
|
||||
// update url, stop spinner, update back/forward
|
||||
currentURL = webView.url
|
||||
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
backButton.isEnabled = webView.canGoBack
|
||||
forwardButton.isEnabled = webView.canGoForward
|
||||
spinner.stopAnimating()
|
||||
|
||||
if navigationDelegate != nil {
|
||||
navigationDelegate?.onLoadStop(uuid: self.uuid, webView: webView)
|
||||
}
|
||||
}
|
||||
|
||||
func webView(_ view: WKWebView,
|
||||
didFailProvisionalNavigation navigation: WKNavigation!,
|
||||
withError error: Error) {
|
||||
webView(view, didFail: navigation, withError: error)
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
||||
backButton.isEnabled = webView.canGoBack
|
||||
forwardButton.isEnabled = webView.canGoForward
|
||||
spinner.stopAnimating()
|
||||
|
||||
if navigationDelegate != nil {
|
||||
navigationDelegate?.onLoadError(uuid: self.uuid, webView: webView, error: error)
|
||||
}
|
||||
}
|
||||
|
||||
func didReceiveResourceResponse(_ response: URLResponse, fromRequest request: URLRequest?, withData data: Data, startTime: Int64, duration: Int64) {
|
||||
if navigationDelegate != nil {
|
||||
navigationDelegate?.onLoadResource(uuid: self.uuid, webView: webView, response: response, fromRequest: request, withData: data, startTime: startTime, duration: duration)
|
||||
}
|
||||
}
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if navigationDelegate != nil {
|
||||
let x = Int(scrollView.contentOffset.x / scrollView.contentScaleFactor)
|
||||
let y = Int(scrollView.contentOffset.y / scrollView.contentScaleFactor)
|
||||
navigationDelegate?.onScrollChanged(uuid: self.uuid, webView: webView, x: x, y: y)
|
||||
}
|
||||
}
|
||||
|
||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||
if message.name.starts(with: "console") {
|
||||
var messageLevel = "LOG"
|
||||
switch (message.name) {
|
||||
case "consoleLog":
|
||||
messageLevel = "LOG"
|
||||
break;
|
||||
case "consoleDebug":
|
||||
// on Android, console.debug is TIP
|
||||
messageLevel = "TIP"
|
||||
break;
|
||||
case "consoleError":
|
||||
messageLevel = "ERROR"
|
||||
break;
|
||||
case "consoleInfo":
|
||||
// on Android, console.info is LOG
|
||||
messageLevel = "LOG"
|
||||
break;
|
||||
case "consoleWarn":
|
||||
messageLevel = "WARNING"
|
||||
break;
|
||||
default:
|
||||
messageLevel = "LOG"
|
||||
break;
|
||||
}
|
||||
if navigationDelegate != nil {
|
||||
navigationDelegate?.onConsoleMessage(uuid: self.uuid, sourceURL: "", lineNumber: 1, message: message.body as! String, messageLevel: messageLevel)
|
||||
}
|
||||
}
|
||||
else if message.name == "resourceLoaded" && (webViewOptions?.useOnLoadResource)! {
|
||||
if let resource = convertToDictionary(text: message.body as! String) {
|
||||
let rawUrl = resource["name"] as! String
|
||||
let encodedUrl = rawUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
|
||||
let url = URL(string: encodedUrl)!
|
||||
if !UIApplication.shared.canOpenURL(url) {
|
||||
return
|
||||
}
|
||||
let startTime = Int64(resource["startTime"] as! Double)
|
||||
let duration = Int64(resource["duration"] as! Double)
|
||||
var urlRequest = URLRequest(url: url)
|
||||
urlRequest.allHTTPHeaderFields = [:]
|
||||
let config = URLSessionConfiguration.default
|
||||
let session = URLSession(configuration: config)
|
||||
let task = session.dataTask(with: urlRequest) { (data, response, error) in
|
||||
if error != nil {
|
||||
print(error)
|
||||
return
|
||||
}
|
||||
var withData = data
|
||||
if withData == nil {
|
||||
withData = Data()
|
||||
}
|
||||
self.didReceiveResourceResponse(response!, fromRequest: urlRequest, withData: withData!, startTime: startTime, duration: duration)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
else if message.name == "callHandler" {
|
||||
let body = message.body as! [String: Any]
|
||||
let handlerName = body["handlerName"] as! String
|
||||
let args = body["args"] as! String
|
||||
if navigationDelegate != nil {
|
||||
self.navigationDelegate?.onCallJsHandler(uuid: self.uuid, webView: webView, handlerName: handlerName, args: args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func takeScreenshot (completionHandler: @escaping (_ screenshot: Data?) -> Void) {
|
||||
if #available(iOS 11.0, *) {
|
||||
self.webView.takeSnapshot(with: nil, completionHandler: {(image, error) -> Void in
|
||||
var imageData: Data? = nil
|
||||
if let screenshot = image {
|
||||
imageData = UIImagePNGRepresentation(screenshot)!
|
||||
}
|
||||
completionHandler(imageData)
|
||||
})
|
||||
} else {
|
||||
completionHandler(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func setOptions(newOptions: InAppBrowserOptions, newOptionsMap: [String: Any]) {
|
||||
|
||||
let newInAppWebViewOptions = InAppWebViewOptions()
|
||||
newInAppWebViewOptions.parse(options: newOptionsMap)
|
||||
self.webView.setOptions(newOptions: newInAppWebViewOptions, newOptionsMap: newOptionsMap)
|
||||
|
||||
if newOptionsMap["hidden"] != nil && browserOptions?.hidden != newOptions.hidden {
|
||||
if newOptions.hidden {
|
||||
|
@ -854,135 +426,18 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
|
|||
if newOptionsMap["transitionStyle"] != nil && browserOptions?.transitionStyle != newOptions.transitionStyle {
|
||||
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: newOptions.transitionStyle)!
|
||||
}
|
||||
|
||||
if newOptionsMap["disallowOverScroll"] != nil && webViewOptions?.disallowOverScroll != newInAppWebViewOptions.disallowOverScroll {
|
||||
if self.webView.responds(to: #selector(getter: self.webView.scrollView)) {
|
||||
self.webView.scrollView.bounces = !newInAppWebViewOptions.disallowOverScroll
|
||||
}
|
||||
else {
|
||||
for subview: UIView in self.webView.subviews {
|
||||
if subview is UIScrollView {
|
||||
(subview as! UIScrollView).bounces = !newInAppWebViewOptions.disallowOverScroll
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["enableViewportScale"] != nil && webViewOptions?.enableViewportScale != newInAppWebViewOptions.enableViewportScale && newInAppWebViewOptions.enableViewportScale {
|
||||
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
|
||||
self.webView.evaluateJavaScript(jscript, completionHandler: nil)
|
||||
}
|
||||
|
||||
if newOptionsMap["mediaPlaybackRequiresUserGesture"] != nil && webViewOptions?.mediaPlaybackRequiresUserGesture != newInAppWebViewOptions.mediaPlaybackRequiresUserGesture {
|
||||
if #available(iOS 10.0, *) {
|
||||
self.webView.configuration.mediaTypesRequiringUserActionForPlayback = (newInAppWebViewOptions.mediaPlaybackRequiresUserGesture) ? .all : []
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
self.webView.configuration.mediaPlaybackRequiresUserAction = newInAppWebViewOptions.mediaPlaybackRequiresUserGesture
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["allowsInlineMediaPlayback"] != nil && webViewOptions?.allowsInlineMediaPlayback != newInAppWebViewOptions.allowsInlineMediaPlayback {
|
||||
self.webView.configuration.allowsInlineMediaPlayback = newInAppWebViewOptions.allowsInlineMediaPlayback
|
||||
}
|
||||
|
||||
// if newOptionsMap["keyboardDisplayRequiresUserAction"] != nil && browserOptions?.keyboardDisplayRequiresUserAction != newOptions.keyboardDisplayRequiresUserAction {
|
||||
// self.webView.keyboardDisplayRequiresUserAction = newOptions.keyboardDisplayRequiresUserAction
|
||||
// }
|
||||
|
||||
if newOptionsMap["suppressesIncrementalRendering"] != nil && webViewOptions?.suppressesIncrementalRendering != newInAppWebViewOptions.suppressesIncrementalRendering {
|
||||
self.webView.configuration.suppressesIncrementalRendering = newInAppWebViewOptions.suppressesIncrementalRendering
|
||||
}
|
||||
|
||||
if newOptionsMap["allowsBackForwardNavigationGestures"] != nil && webViewOptions?.allowsBackForwardNavigationGestures != newInAppWebViewOptions.allowsBackForwardNavigationGestures {
|
||||
self.webView.allowsBackForwardNavigationGestures = newInAppWebViewOptions.allowsBackForwardNavigationGestures
|
||||
}
|
||||
|
||||
if newOptionsMap["allowsLinkPreview"] != nil && webViewOptions?.allowsLinkPreview != newInAppWebViewOptions.allowsLinkPreview {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.allowsLinkPreview = newInAppWebViewOptions.allowsLinkPreview
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["ignoresViewportScaleLimits"] != nil && webViewOptions?.ignoresViewportScaleLimits != newInAppWebViewOptions.ignoresViewportScaleLimits {
|
||||
if #available(iOS 10.0, *) {
|
||||
self.webView.configuration.ignoresViewportScaleLimits = newInAppWebViewOptions.ignoresViewportScaleLimits
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["allowsInlineMediaPlayback"] != nil && webViewOptions?.allowsInlineMediaPlayback != newInAppWebViewOptions.allowsInlineMediaPlayback {
|
||||
self.webView.configuration.allowsInlineMediaPlayback = newInAppWebViewOptions.allowsInlineMediaPlayback
|
||||
}
|
||||
|
||||
if newOptionsMap["allowsPictureInPictureMediaPlayback"] != nil && webViewOptions?.allowsPictureInPictureMediaPlayback != newInAppWebViewOptions.allowsPictureInPictureMediaPlayback {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.configuration.allowsPictureInPictureMediaPlayback = newInAppWebViewOptions.allowsPictureInPictureMediaPlayback
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["javaScriptCanOpenWindowsAutomatically"] != nil && webViewOptions?.javaScriptCanOpenWindowsAutomatically != newInAppWebViewOptions.javaScriptCanOpenWindowsAutomatically {
|
||||
self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = newInAppWebViewOptions.javaScriptCanOpenWindowsAutomatically
|
||||
}
|
||||
|
||||
if newOptionsMap["javaScriptEnabled"] != nil && webViewOptions?.javaScriptEnabled != newInAppWebViewOptions.javaScriptEnabled {
|
||||
self.webView.configuration.preferences.javaScriptEnabled = newInAppWebViewOptions.javaScriptEnabled
|
||||
}
|
||||
|
||||
if newOptionsMap["userAgent"] != nil && webViewOptions?.userAgent != newInAppWebViewOptions.userAgent && (newInAppWebViewOptions.userAgent != "") {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.customUserAgent = newInAppWebViewOptions.userAgent
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["clearCache"] != nil && newInAppWebViewOptions.clearCache {
|
||||
clearCache()
|
||||
}
|
||||
|
||||
self.browserOptions = newOptions
|
||||
self.webViewOptions = newInAppWebViewOptions
|
||||
}
|
||||
|
||||
func getOptions() -> [String: Any]? {
|
||||
if (self.browserOptions == nil || self.webViewOptions == nil) {
|
||||
if (self.browserOptions == nil || self.webView.getOptions() == nil) {
|
||||
return nil
|
||||
}
|
||||
var optionsMap = self.browserOptions!.getHashMap()
|
||||
optionsMap.merge(self.webViewOptions!.getHashMap(), uniquingKeysWith: { (current, _) in current })
|
||||
optionsMap.merge(self.webView.getOptions()!, uniquingKeysWith: { (current, _) in current })
|
||||
return optionsMap
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?,
|
||||
change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "estimatedProgress" {
|
||||
let progress = Int(webView.estimatedProgress * 100)
|
||||
self.navigationDelegate?.onProgressChanged(uuid: self.uuid, webView: self.webView, progress: progress)
|
||||
}
|
||||
}
|
||||
|
||||
func getCopyBackForwardList() -> [String: Any] {
|
||||
let currentList = self.webView.backForwardList
|
||||
let currentIndex = currentList.backList.count
|
||||
var completeList = currentList.backList
|
||||
if currentList.currentItem != nil {
|
||||
completeList.append(currentList.currentItem!)
|
||||
}
|
||||
completeList.append(contentsOf: currentList.forwardList)
|
||||
|
||||
var history: [[String: String]] = []
|
||||
|
||||
for historyItem in completeList {
|
||||
var historyItemMap: [String: String] = [:]
|
||||
historyItemMap["originalUrl"] = historyItem.initialURL.absoluteString
|
||||
historyItemMap["title"] = historyItem.title
|
||||
historyItemMap["url"] = historyItem.url.absoluteString
|
||||
history.append(historyItemMap)
|
||||
}
|
||||
|
||||
var result: [String: Any] = [:]
|
||||
result["history"] = history
|
||||
result["currentIndex"] = currentIndex
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,73 @@
|
|||
import Foundation
|
||||
import WebKit
|
||||
|
||||
func currentTimeInMilliSeconds() -> Int64 {
|
||||
let currentDate = Date()
|
||||
let since1970 = currentDate.timeIntervalSince1970
|
||||
return Int64(since1970 * 1000)
|
||||
}
|
||||
|
||||
func convertToDictionary(text: String) -> [String: Any]? {
|
||||
if let data = text.data(using: .utf8) {
|
||||
do {
|
||||
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// the message needs to be concatenated with '' in order to have the same behavior like on Android
|
||||
let consoleLogJS = """
|
||||
(function() {
|
||||
var oldLogs = {
|
||||
'consoleLog': console.log,
|
||||
'consoleDebug': console.debug,
|
||||
'consoleError': console.error,
|
||||
'consoleInfo': console.info,
|
||||
'consoleWarn': console.warn
|
||||
};
|
||||
|
||||
for (var k in oldLogs) {
|
||||
(function(oldLog) {
|
||||
console[oldLog.replace('console', '').toLowerCase()] = function() {
|
||||
var message = '';
|
||||
for (var i in arguments) {
|
||||
if (message == '') {
|
||||
message += arguments[i];
|
||||
}
|
||||
else {
|
||||
message += ' ' + arguments[i];
|
||||
}
|
||||
}
|
||||
window.webkit.messageHandlers[oldLog].postMessage(message);
|
||||
}
|
||||
})(k);
|
||||
}
|
||||
})();
|
||||
"""
|
||||
|
||||
let resourceObserverJS = """
|
||||
(function() {
|
||||
var observer = new PerformanceObserver(function(list) {
|
||||
list.getEntries().forEach(function(entry) {
|
||||
window.webkit.messageHandlers['resourceLoaded'].postMessage(JSON.stringify(entry));
|
||||
});
|
||||
});
|
||||
observer.observe({entryTypes: ['resource', 'mark', 'measure']});
|
||||
})();
|
||||
"""
|
||||
|
||||
let JAVASCRIPT_BRIDGE_NAME = "flutter_inappbrowser"
|
||||
|
||||
let javaScriptBridgeJS = """
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME) = {};
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function(handlerName, ...args) {
|
||||
window.webkit.messageHandlers['callHandler'].postMessage( {'handlerName': handlerName, 'args': JSON.stringify(args)} );
|
||||
}
|
||||
"""
|
||||
|
||||
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {
|
||||
|
||||
var IABController: InAppBrowserWebViewController?
|
||||
|
@ -87,7 +154,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
configuration.mediaPlaybackRequiresUserAction = (options?.mediaPlaybackRequiresUserGesture)!
|
||||
}
|
||||
|
||||
|
||||
configuration.allowsInlineMediaPlayback = (options?.allowsInlineMediaPlayback)!
|
||||
|
||||
//keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction
|
||||
|
@ -436,6 +502,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
if navigationAction.navigationType == .linkActivated || navigationAction.navigationType == .backForward {
|
||||
currentURL = url
|
||||
if IABController != nil {
|
||||
IABController!.updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,14 +529,66 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
decisionHandler(.allow)
|
||||
}
|
||||
|
||||
// func webView(_ webView: WKWebView,
|
||||
// decidePolicyFor navigationResponse: WKNavigationResponse,
|
||||
// decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
|
||||
// let mimeType = navigationResponse.response.mimeType
|
||||
// if mimeType != nil && !mimeType!.starts(with: "text/") {
|
||||
// download(url: webView.url)
|
||||
// decisionHandler(.cancel)
|
||||
// return
|
||||
// }
|
||||
// decisionHandler(.allow)
|
||||
// }
|
||||
//
|
||||
// func download (url: URL?) {
|
||||
// let filename = url?.lastPathComponent
|
||||
//
|
||||
// let destination: DownloadRequest.DownloadFileDestination = { _, _ in
|
||||
// let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||
// let fileURL = documentsURL.appendingPathComponent(filename!)
|
||||
//
|
||||
// return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
|
||||
// }
|
||||
//
|
||||
// Alamofire.download((url?.absoluteString)!, to: destination).downloadProgress { progress in
|
||||
// print("Download Progress: \(progress.fractionCompleted)")
|
||||
// }.response { response in
|
||||
// if response.error == nil, let path = response.destinationURL?.path {
|
||||
// UIAlertView(title: nil, message: "File saved to " + path, delegate: nil, cancelButtonTitle: nil).show()
|
||||
// }
|
||||
// else {
|
||||
// UIAlertView(title: nil, message: "Cannot save " + filename!, delegate: nil, cancelButtonTitle: nil).show()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
||||
self.startPageTime = currentTimeInMilliSeconds()
|
||||
onLoadStart(url: (currentURL?.absoluteString)!)
|
||||
|
||||
if IABController != nil {
|
||||
// loading url, start spinner, update back/forward
|
||||
IABController!.backButton.isEnabled = canGoBack
|
||||
IABController!.forwardButton.isEnabled = canGoForward
|
||||
|
||||
if (IABController!.browserOptions?.spinner)! {
|
||||
IABController!.spinner.startAnimating()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
self.WKNavigationMap = [:]
|
||||
onLoadStop(url: (url?.absoluteString)!)
|
||||
currentURL = url
|
||||
onLoadStop(url: (currentURL?.absoluteString)!)
|
||||
|
||||
if IABController != nil {
|
||||
IABController!.updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
IABController!.backButton.isEnabled = canGoBack
|
||||
IABController!.forwardButton.isEnabled = canGoForward
|
||||
IABController!.spinner.stopAnimating()
|
||||
}
|
||||
}
|
||||
|
||||
public func webView(_ view: WKWebView,
|
||||
|
@ -478,6 +599,12 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
||||
onLoadError(url: (currentURL?.absoluteString)!, error: error)
|
||||
|
||||
if IABController != nil {
|
||||
IABController!.backButton.isEnabled = canGoBack
|
||||
IABController!.forwardButton.isEnabled = canGoForward
|
||||
IABController!.spinner.stopAnimating()
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
|
@ -609,7 +736,10 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
}
|
||||
else if message.name == "resourceLoaded" && (options?.useOnLoadResource)! {
|
||||
if let resource = convertToDictionary(text: message.body as! String) {
|
||||
let url = URL(string: resource["name"] as! String)!
|
||||
// escape special chars
|
||||
let resourceName = (resource["name"] as! String).addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
|
||||
|
||||
let url = URL(string: resourceName!)!
|
||||
if !UIApplication.shared.canOpenURL(url) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
break
|
||||
case "takeScreenshot":
|
||||
if let webViewController = self.webViewControllers[uuid] {
|
||||
webViewController!.takeScreenshot(completionHandler: { (screenshot) -> Void in
|
||||
webViewController!.webView.takeScreenshot(completionHandler: { (screenshot) -> Void in
|
||||
result(screenshot)
|
||||
})
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
webViewController.webViewOptions = webViewOptions
|
||||
webViewController.isHidden = browserOptions.hidden
|
||||
webViewController.tmpWindow = tmpWindow
|
||||
webViewController.currentURL = url
|
||||
webViewController.initURL = url
|
||||
webViewController.initHeaders = headers
|
||||
webViewController.navigationDelegate = self
|
||||
|
||||
|
@ -708,21 +708,21 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
|
||||
func onLoadStart(uuid: String, webView: WKWebView) {
|
||||
if let webViewController = self.webViewControllers[uuid] {
|
||||
let url: String = webViewController!.currentURL!.absoluteString
|
||||
let url: String = webViewController!.webView.currentURL!.absoluteString
|
||||
SwiftFlutterPlugin.channel!.invokeMethod("onLoadStart", arguments: ["uuid": uuid, "url": url])
|
||||
}
|
||||
}
|
||||
|
||||
func onLoadStop(uuid: String, webView: WKWebView) {
|
||||
if let webViewController = self.webViewControllers[uuid] {
|
||||
let url: String = webViewController!.currentURL!.absoluteString
|
||||
let url: String = webViewController!.webView.currentURL!.absoluteString
|
||||
SwiftFlutterPlugin.channel!.invokeMethod("onLoadStop", arguments: ["uuid": uuid, "url": url])
|
||||
}
|
||||
}
|
||||
|
||||
func onLoadError(uuid: String, webView: WKWebView, error: Error) {
|
||||
if let webViewController = self.webViewControllers[uuid] {
|
||||
let url: String = webViewController!.currentURL!.absoluteString
|
||||
let url: String = webViewController!.webView.currentURL!.absoluteString
|
||||
let arguments = ["uuid": uuid, "url": url, "code": error._code, "message": error.localizedDescription] as [String : Any]
|
||||
SwiftFlutterPlugin.channel!.invokeMethod("onLoadError", arguments: arguments)
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
|
||||
func getCopyBackForwardList(uuid: String) -> [String: Any]? {
|
||||
if let webViewController = self.webViewControllers[uuid] {
|
||||
return webViewController!.getCopyBackForwardList()
|
||||
return webViewController!.webView.getCopyBackForwardList()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_inappbrowser
|
||||
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window (inspired by the popular cordova-plugin-inappbrowser).
|
||||
version: 0.5.51
|
||||
version: 0.6.0
|
||||
author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
|
||||
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
|
||||
|
||||
|
@ -11,7 +11,7 @@ environment:
|
|||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
uuid: ^1.0.3
|
||||
uuid: ^2.0.0
|
||||
mime: ^0.9.6+2
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
|
|
Loading…
Reference in New Issue