~cytrogen/fluent-reader-mobile

3499ce58cb00fabfff8274435d52f8909502bff7 — 刘浩远 5 years ago 0b77b46
switch to third party webview
5 files changed, 92 insertions(+), 86 deletions(-)

M android/app/build.gradle
M assets/article/article.js
M lib/pages/article_page.dart
M pubspec.lock
M pubspec.yaml
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