M assets/article/article.js => assets/article/article.js +46 -47
@@ 1,53 1,52 @@
-function r(params) {
- function get(name) {
- if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(params))
- return decodeURIComponent(name[1])
- return null
+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
}
- async function getArticle(url) {
- let article = get("a")
- if (get("m") === "1") {
- return (await Mercury.parse(url, {html: article})).content || ""
- } else {
- return article
- }
+}
+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)
}
- 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("*[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 ios/Podfile.lock => ios/Podfile.lock +6 -6
@@ 1,7 1,5 @@
PODS:
- Flutter (1.0.0)
- - flutter_inappwebview (0.0.1):
- - Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
@@ 18,16 16,18 @@ PODS:
- FMDB (>= 2.7.5)
- url_launcher (0.0.1):
- Flutter
+ - webview_flutter (0.0.1):
+ - Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- - flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- share (from `.symlinks/plugins/share/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
+ - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
SPEC REPOS:
trunk:
@@ 36,8 36,6 @@ SPEC REPOS:
EXTERNAL SOURCES:
Flutter:
:path: Flutter
- flutter_inappwebview:
- :path: ".symlinks/plugins/flutter_inappwebview/ios"
package_info:
:path: ".symlinks/plugins/package_info/ios"
path_provider:
@@ 50,10 48,11 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher:
:path: ".symlinks/plugins/url_launcher/ios"
+ webview_flutter:
+ :path: ".symlinks/plugins/webview_flutter/ios"
SPEC CHECKSUMS:
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
- flutter_inappwebview: 69dfbac46157b336ffbec19ca6dfd4638c7bf189
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
@@ 61,6 60,7 @@ SPEC CHECKSUMS:
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
+ webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
M lib/main.dart => lib/main.dart +2 -0
@@ 22,6 22,7 @@ import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
import 'package:path/path.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:webview_flutter/webview_flutter.dart';
import 'generated/l10n.dart';
import 'models/global_model.dart';
@@ 33,6 34,7 @@ void main() async {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
));
+ WebView.platform = SurfaceAndroidWebView();
}
runApp(MyApp());
SystemChannels.lifecycle.setMessageHandler((msg) {
M lib/pages/article_page.dart => lib/pages/article_page.dart +24 -40
@@ 11,7 11,6 @@ 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';
@@ 19,6 18,7 @@ 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/webview_flutter.dart';
class ArticlePage extends StatefulWidget {
static final GlobalKey<ArticlePageState> state = GlobalKey();
@@ 30,22 30,13 @@ class ArticlePage extends StatefulWidget {
}
class ArticlePageState extends State<ArticlePage> {
- InAppWebViewController _controller;
+ WebViewController _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) {
@@ 60,21 51,17 @@ class ArticlePageState extends State<ArticlePage> {
});
}
- Future<bool> _onNewWindow(_, CreateWindowRequest request) async {
- await launch(request.url);
- return false;
- }
-
- Future<ShouldOverrideUrlLoadingAction> _onNavigate(_, ShouldOverrideUrlLoadingRequest request) async {
+ Future<NavigationDecision> _onNavigate(NavigationRequest request) async {
if (navigated && request.isForMainFrame) {
await launch(request.url);
- return ShouldOverrideUrlLoadingAction.CANCEL;
+ return NavigationDecision.prevent;
+ } else {
+ return NavigationDecision.navigate;
}
- return ShouldOverrideUrlLoadingAction.ALLOW;
}
void _loadHtml(RSSItem item, RSSSource source, {loadFull: false}) async {
- var localUrl = "assets/article/article.html";
+ var localUrl = "http://127.0.0.1:9000/article/article.html";
var currId = requestId;
String a;
if (loadFull) {
@@ 94,23 81,22 @@ class ArticlePageState extends State<ArticlePage> {
h += '<article></article>';
h = Uri.encodeComponent(h);
var s = Store.getArticleFontSize();
- localParams = "?a=$a&h=$h&s=$s&u=${item.link}&m=${loadFull ? 1 : 0}";
+ localUrl += "?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);
- localParams += "&t=${brightness.index}";
+ localUrl += "&t=${brightness.index}";
}
- if (currId == requestId) _controller.loadFile(assetFilePath: localUrl);
-
+ if (currId == requestId) _controller.loadUrl(localUrl);
}
- void _onPageReady(_, String url) async {
- if (url != "about:blank") {
- if (localParams != null) {
- _controller.evaluateJavascript(source: 'r("$localParams")');
- setState(() { loaded = true; });
- }
- navigated = true;
+ void _onPageReady(_) async {
+ if (Platform.isAndroid || Global.globalModel.getBrightness() != null) {
+ await Future.delayed(Duration(milliseconds: 300));
}
+ setState(() { loaded = true; });
+ }
+ void _onWebpageReady(_) {
+ if (loaded) navigated = true;
}
void _setOpenTarget(RSSSource source, {SourceOpenTarget target}) {
@@ 134,9 120,7 @@ class ArticlePageState extends State<ArticlePage> {
break;
case SourceOpenTarget.Webpage:
case SourceOpenTarget.External:
- localParams = null;
- _controller.loadUrl(url: item.link);
- setState(() { loaded = true; });
+ _controller.loadUrl(item.link);
break;
}
}
@@ 168,16 152,16 @@ class ArticlePageState extends State<ArticlePage> {
Center(
child: CupertinoActivityIndicator()
),
- InAppWebView(
+ WebView(
key: Key("a-$iid-${_target.index}"),
- onWebViewCreated: (InAppWebViewController webViewController) {
+ javascriptMode: JavascriptMode.unrestricted,
+ onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
_loadOpenTarget(item, source);
},
- onLoadStop: _onPageReady,
- onCreateWindow: _onNewWindow,
- shouldOverrideUrlLoading: _onNavigate,
- initialOptions: _webViewOptions,
+ onPageStarted: _onPageReady,
+ onPageFinished: _onWebpageReady,
+ navigationDelegate: _onNavigate,
),
],
), bottom: false,);
M lib/pages/settings/services/feedbin_page.dart => lib/pages/settings/services/feedbin_page.dart +2 -0
@@ 84,6 84,7 @@ class _FeedbinPageState extends State<FeedbinPage> {
await Global.syncModel.syncWithService();
Global.syncModel.checkHasService();
_validating = false;
+ DialogHelper().hide(context);
if (mounted) Navigator.of(context).pop();
} else {
setState(() { _validating = false; });
@@ 122,6 123,7 @@ class _FeedbinPageState extends State<FeedbinPage> {
DialogWidget.progress(style: DialogStyle.cupertino),
);
await Global.syncModel.removeService();
+ DialogHelper().hide(context);
final navigator = Navigator.of(context);
while (navigator.canPop()) navigator.pop();
}
M lib/pages/settings/services/fever_page.dart => lib/pages/settings/services/fever_page.dart +2 -0
@@ 87,6 87,7 @@ class _FeverPageState extends State<FeverPage> {
await Global.syncModel.syncWithService();
Global.syncModel.checkHasService();
_validating = false;
+ DialogHelper().hide(context);
if (mounted) Navigator.of(context).pop();
} else {
setState(() { _validating = false; });
@@ 125,6 126,7 @@ class _FeverPageState extends State<FeverPage> {
DialogWidget.progress(style: DialogStyle.cupertino),
);
await Global.syncModel.removeService();
+ DialogHelper().hide(context);
final navigator = Navigator.of(context);
while (navigator.canPop()) navigator.pop();
}
M lib/utils/global.dart => lib/utils/global.dart +6 -0
@@ 10,6 10,8 @@ import 'package:fluent_reader_lite/models/sync_model.dart';
import 'package:fluent_reader_lite/utils/db.dart';
import 'package:fluent_reader_lite/utils/store.dart';
import 'package:flutter/cupertino.dart';
+import 'package:jaguar/serve/server.dart';
+import 'package:jaguar_flutter_asset/jaguar_flutter_asset.dart';
import 'package:sqflite/sqflite.dart';
abstract class Global {
@@ 22,6 24,7 @@ abstract class Global {
static SyncModel syncModel;
static ServiceHandler service;
static Database db;
+ static Jaguar server;
static final GlobalKey<NavigatorState> tabletPanel = GlobalKey();
static void init() {
@@ 64,6 67,9 @@ abstract class Global {
.millisecondsSinceEpoch,
],
);
+ server = Jaguar(address: "127.0.0.1",port: 9000);
+ server.addRoute(serveFlutterAssets());
+ await server.serve();
await sourcesModel.init();
await feedsModel.all.init();
if (globalModel.syncOnStart) await syncModel.syncWithService();
M pubspec.lock => pubspec.lock +63 -7
@@ 22,6 22,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.0-nullsafety.3"
+ auth_header:
+ dependency: transitive
+ description:
+ name: auth_header
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.4"
boolean_selector:
dependency: transitive
description:
@@ 132,13 139,6 @@ 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
@@ 175,6 175,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.4"
+ http_server:
+ dependency: transitive
+ description:
+ name: http_server
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.9.8+3"
image:
dependency: transitive
description:
@@ 189,6 196,34 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.17.0-nullsafety.2"
+ jaguar:
+ dependency: "direct main"
+ description:
+ name: jaguar
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.4.46"
+ jaguar_common:
+ dependency: transitive
+ description:
+ name: jaguar_common
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.4"
+ jaguar_flutter_asset:
+ dependency: "direct main"
+ description:
+ name: jaguar_flutter_asset
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.0"
+ jaguar_serializer:
+ dependency: transitive
+ description:
+ name: jaguar_serializer
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.12"
js:
dependency: transitive
description:
@@ 196,6 231,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.6.3-nullsafety.3"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.11.4"
matcher:
dependency: transitive
description:
@@ 294,6 336,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.4+3"
+ path_tree:
+ dependency: transitive
+ description:
+ name: path_tree
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.4"
pedantic:
dependency: transitive
description:
@@ 544,6 593,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.5"
+ webview_flutter:
+ dependency: "direct main"
+ description:
+ name: webview_flutter
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.0.0-nullsafety.3"
win32:
dependency: transitive
description:
M pubspec.yaml => pubspec.yaml +3 -1
@@ 31,7 31,9 @@ dependencies:
intl: ^0.17.0-nullsafety.2
http: ^0.12.2
html: ^0.14.0+4
- flutter_inappwebview: ^4.0.0+4
+ webview_flutter: ^2.0.0-nullsafety.3
+ jaguar: ^2.4.46
+ jaguar_flutter_asset: ^2.2.0
url_launcher: ^5.7.10
sqflite: ^1.3.2+1
path: ^1.7.0