From 3499ce58cb00fabfff8274435d52f8909502bff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B5=A9=E8=BF=9C?= Date: Mon, 18 Jan 2021 10:52:19 +0800 Subject: [PATCH] switch to third party webview --- android/app/build.gradle | 2 +- assets/article/article.js | 93 +++++++++++++++++++------------------ lib/pages/article_page.dart | 60 ++++++++++++++---------- pubspec.lock | 21 +++------ pubspec.yaml | 2 +- 5 files changed, 92 insertions(+), 86 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 9760fb7..0d6442d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -39,7 +39,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "me.hyliu.fluent_reader_lite" - minSdkVersion 16 + minSdkVersion 24 targetSdkVersion 29 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/assets/article/article.js b/assets/article/article.js index b71bc03..9241569 100644 --- a/assets/article/article.js +++ b/assets/article/article.js @@ -1,52 +1,53 @@ -function get(name) { - if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search)) - return decodeURIComponent(name[1]) - return null -} -async function getArticle(url) { - let article = get("a") - if (get("m") === "1") { - return (await Mercury.parse(url, {html: article})).content || "" - } else { - return article +function r(params) { + function get(name) { + if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(params)) + return decodeURIComponent(name[1]) + return null } -} -document.documentElement.style.fontSize = get("s") + "px" -let theme = get("t") -if (theme !== null) document.documentElement.classList.add(theme === "1" ? "light" : "dark") -let url = get("u") -getArticle(url).then(article => { - let domParser = new DOMParser() - let dom = domParser.parseFromString(get("h"), "text/html") - dom.getElementsByTagName("article")[0].innerHTML = article - let baseUrl = url.split("/").slice(0, 3).join("/") - for (let s of dom.getElementsByTagName("script")) { - s.parentNode.removeChild(s) + async function getArticle(url) { + let article = get("a") + if (get("m") === "1") { + return (await Mercury.parse(url, {html: article})).content || "" + } else { + return article + } } - for (let e of dom.querySelectorAll("*[src]")) { - if (e.src && !e.src.startsWith("http")) { - if (e.src.startsWith("/")) { - e.src = baseUrl + e.src - } else if (e.src.startsWith(":")) { - e.src = "http" + e.src - } else { - e.src = baseUrl + "/" + e.src + document.documentElement.style.fontSize = get("s") + "px" + let theme = get("t") + if (theme !== null) document.documentElement.classList.add(theme === "1" ? "light" : "dark") + let url = get("u") + getArticle(url).then(article => { + let domParser = new DOMParser() + let dom = domParser.parseFromString(get("h"), "text/html") + dom.getElementsByTagName("article")[0].innerHTML = article + let baseUrl = url.split("/").slice(0, 3).join("/") + for (let s of dom.getElementsByTagName("script")) { + s.parentNode.removeChild(s) + } + for (let e of dom.querySelectorAll("*[src]")) { + if (e.src && !e.src.startsWith("http")) { + if (e.src.startsWith("/")) { + e.src = baseUrl + e.src + } else if (e.src.startsWith(":")) { + e.src = "http" + e.src + } else { + e.src = baseUrl + "/" + e.src + } } } - } - for (let e of dom.querySelectorAll("*[href]")) { - if (e.href && !e.href.startsWith("http")) { - if (e.href.startsWith("/")) { - e.href = baseUrl + e.href - } else if (e.href.startsWith(":")) { - e.href = "http" + e.href - } else { - e.href = baseUrl + "/" + e.href + for (let e of dom.querySelectorAll("*[href]")) { + if (e.href && !e.href.startsWith("http")) { + if (e.href.startsWith("/")) { + e.href = baseUrl + e.href + } else if (e.href.startsWith(":")) { + e.href = "http" + e.href + } else { + e.href = baseUrl + "/" + e.href + } } } - } - let main = document.getElementById("main") - main.innerHTML = dom.body.innerHTML - main.classList.add("show") -}) - + let main = document.getElementById("main") + main.innerHTML = dom.body.innerHTML + main.classList.add("show") + }) +} diff --git a/lib/pages/article_page.dart b/lib/pages/article_page.dart index f33f887..45ada17 100644 --- a/lib/pages/article_page.dart +++ b/lib/pages/article_page.dart @@ -11,6 +11,7 @@ import 'package:fluent_reader_lite/utils/global.dart'; import 'package:fluent_reader_lite/utils/store.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:intl/intl.dart'; import 'package:http/http.dart' as http; import 'package:provider/provider.dart'; @@ -18,7 +19,6 @@ import 'package:tuple/tuple.dart'; import 'package:share/share.dart'; import 'package:fluent_reader_lite/components/cupertino_toolbar.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:webview_flutter_plus/webview_flutter_plus.dart'; class ArticlePage extends StatefulWidget { static final GlobalKey state = GlobalKey(); @@ -30,13 +30,22 @@ class ArticlePage extends StatefulWidget { } class ArticlePageState extends State { - WebViewPlusController _controller; + InAppWebViewController _controller; int requestId = 0; bool loaded = false; bool navigated = false; SourceOpenTarget _target; String iid; bool isSourceFeed; + String localParams; + + static final _webViewOptions = InAppWebViewGroupOptions( + crossPlatform: InAppWebViewOptions( + useShouldOverrideUrlLoading: true, + debuggingEnabled: true, + transparentBackground: true, + ), + ); void loadNewItem(String id, {bool isSource}) { if (!Global.itemsModel.getItem(id).hasRead) { @@ -51,13 +60,17 @@ class ArticlePageState extends State { }); } - Future _onNavigate(NavigationRequest request) async { - if (navigated && request.isForMainFrame) { + Future _onNewWindow(_, CreateWindowRequest request) async { + await launch(request.url); + return false; + } + + Future _onNavigate(_, ShouldOverrideUrlLoadingRequest request) async { + if (loaded && request.isForMainFrame) { await launch(request.url); - return NavigationDecision.prevent; - } else { - return NavigationDecision.navigate; + return ShouldOverrideUrlLoadingAction.CANCEL; } + return ShouldOverrideUrlLoadingAction.ALLOW; } void _loadHtml(RSSItem item, RSSSource source, {loadFull: false}) async { @@ -81,22 +94,20 @@ class ArticlePageState extends State { h += '
'; h = Uri.encodeComponent(h); var s = Store.getArticleFontSize(); - localUrl += "?a=$a&h=$h&s=$s&u=${item.link}&m=${loadFull ? 1 : 0}"; + localParams = "?a=$a&h=$h&s=$s&u=${item.link}&m=${loadFull ? 1 : 0}"; if (Platform.isAndroid || Global.globalModel.getBrightness() != null) { var brightness = Global.currentBrightness(context); - localUrl += "&t=${brightness.index}"; + localParams += "&t=${brightness.index}"; } - if (currId == requestId) _controller.loadUrl(localUrl); + if (currId == requestId) _controller.loadFile(assetFilePath: localUrl); + } - void _onPageReady(_) async { - if (Platform.isAndroid || Global.globalModel.getBrightness() != null) { - await Future.delayed(Duration(milliseconds: 300)); + void _onPageReady(_, String url) async { + if (url != "about:blank") { + _controller.evaluateJavascript(source: 'r("$localParams")'); + setState(() { loaded = true; }); } - setState(() { loaded = true; }); - } - void _onWebpageReady(_) { - if (loaded) navigated = true; } void _setOpenTarget(RSSSource source, {SourceOpenTarget target}) { @@ -120,7 +131,8 @@ class ArticlePageState extends State { break; case SourceOpenTarget.Webpage: case SourceOpenTarget.External: - _controller.loadUrl(item.link); + localParams = null; + _controller.loadUrl(url: item.link); break; } } @@ -152,16 +164,16 @@ class ArticlePageState extends State { Center( child: CupertinoActivityIndicator() ), - WebViewPlus( + InAppWebView( key: Key("a-$iid-${_target.index}"), - javascriptMode: JavascriptMode.unrestricted, - onWebViewCreated: (WebViewPlusController webViewController) { + onWebViewCreated: (InAppWebViewController webViewController) { _controller = webViewController; _loadOpenTarget(item, source); }, - onPageStarted: _onPageReady, - onPageFinished: _onWebpageReady, - navigationDelegate: _onNavigate, + onLoadStop: _onPageReady, + onCreateWindow: _onNewWindow, + shouldOverrideUrlLoading: _onNavigate, + initialOptions: _webViewOptions, ), ], ), bottom: false,); diff --git a/pubspec.lock b/pubspec.lock index a16c0fe..4948767 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -132,6 +132,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" + flutter_inappwebview: + dependency: "direct main" + description: + name: flutter_inappwebview + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.0.0+4" flutter_localizations: dependency: "direct main" description: flutter @@ -530,20 +537,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0-nullsafety.5" - webview_flutter: - dependency: transitive - description: - name: webview_flutter - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.7" - webview_flutter_plus: - dependency: "direct main" - description: - name: webview_flutter_plus - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.1.1+10" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0efe8e5..9ce6136 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,7 +31,7 @@ dependencies: intl: ^0.17.0-nullsafety.2 http: ^0.12.2 html: ^0.14.0+4 - webview_flutter_plus: ^0.1.1+10 + flutter_inappwebview: ^4.0.0+4 url_launcher: ^5.7.10 sqflite: ^1.3.2+1 path: ^1.7.0 -- 2.38.5