M android/app/build.gradle => android/app/build.gradle +1 -1
@@ 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
M assets/article/article.js => assets/article/article.js +47 -46
@@ 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")
+ })
+}
M lib/pages/article_page.dart => lib/pages/article_page.dart +36 -24
@@ 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<ArticlePageState> state = GlobalKey();
@@ 30,13 30,22 @@ class ArticlePage extends StatefulWidget {
}
class ArticlePageState extends State<ArticlePage> {
- 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<ArticlePage> {
});
}
- Future<NavigationDecision> _onNavigate(NavigationRequest request) async {
- if (navigated && request.isForMainFrame) {
+ Future<bool> _onNewWindow(_, CreateWindowRequest request) async {
+ await launch(request.url);
+ return false;
+ }
+
+ Future<ShouldOverrideUrlLoadingAction> _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<ArticlePage> {
h += '<article></article>';
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<ArticlePage> {
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<ArticlePage> {
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,);
M pubspec.lock => pubspec.lock +7 -14
@@ 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:
M pubspec.yaml => pubspec.yaml +1 -1
@@ 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