M lib/l10n/intl_en.arb => lib/l10n/intl_en.arb +2 -1
@@ 61,7 61,8 @@
"clearCache": "Clear cache",
"autoDelete": "Auto delete items",
"sync": "Sync",
- "onStart": "On start",
+ "syncOnStart": "Sync on start",
+ "inAppBrowser": "In-app browser",
"lastSyncSuccess": "Last sync successful at",
"lastSyncFailure": "Last sync failed at",
"welcome": "Welcome",
M lib/l10n/intl_zh.arb => lib/l10n/intl_zh.arb +2 -1
@@ 61,7 61,8 @@
"clearCache": "清理缓存",
"autoDelete": "自动删除文章",
"sync": "同步",
- "onStart": "打开应用时",
+ "syncOnStart": "打开应用时同步",
+ "inAppBrowser": "应用内浏览器",
"lastSyncSuccess": "最后一次同步成功于",
"lastSyncFailure": "最后一次同步失败于",
"welcome": "欢迎",
M lib/main.dart => lib/main.dart +12 -3
@@ 19,7 19,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
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';
@@ 39,9 38,11 @@ void main() async {
runApp(MyApp());
SystemChannels.lifecycle.setMessageHandler((msg) {
if (msg == AppLifecycleState.resumed.toString()) {
+ if (Global.server != null) Global.server.restart();
if (Global.globalModel.syncOnStart
- && DateTime.now().difference(Global.syncModel.lastSynced).inMinutes >= 10)
- Global.syncModel.syncWithService();
+ && DateTime.now().difference(Global.syncModel.lastSynced).inMinutes >= 10) {
+ Global.syncModel.syncWithService();
+ }
}
return null;
});
@@ 119,6 120,14 @@ class MyApp extends StatelessWidget {
"/": (context) => CupertinoScaffold(body: HomePage()),
...baseRoutes,
},
+ builder: (context, child) {
+ final mediaQueryData = MediaQuery.of(context);
+ if (Global.globalModel.textScale == null) return child;
+ return MediaQuery(
+ data: mediaQueryData.copyWith(textScaleFactor: Global.globalModel.textScale),
+ child: child
+ );
+ },
),
),
);
M lib/models/global_model.dart => lib/models/global_model.dart +23 -0
@@ 1,3 1,5 @@
+import 'dart:io';
+
import 'package:fluent_reader_lite/utils/store.dart';
import 'package:flutter/material.dart';
@@ 10,6 12,8 @@ class GlobalModel with ChangeNotifier {
Locale _locale = Store.getLocale();
int _keepItemsDays = Store.sp.getInt(StoreKeys.KEEP_ITEMS_DAYS) ?? 21;
bool _syncOnStart = Store.sp.getBool(StoreKeys.SYNC_ON_START) ?? true;
+ bool _inAppBrowser = Store.sp.getBool(StoreKeys.IN_APP_BROWSER) ?? Platform.isIOS;
+ double _textScale = Store.sp.getDouble(StoreKeys.TEXT_SCALE);
ThemeSetting get theme => _theme;
set theme(ThemeSetting value) {
@@ 44,4 48,23 @@ class GlobalModel with ChangeNotifier {
_syncOnStart = value;
Store.sp.setBool(StoreKeys.SYNC_ON_START, value);
}
+
+ bool get inAppBrowser => _inAppBrowser;
+ set inAppBrowser(bool value) {
+ _inAppBrowser = value;
+ Store.sp.setBool(StoreKeys.IN_APP_BROWSER, value);
+ }
+
+ double get textScale => _textScale;
+ set textScale(double value) {
+ if (_textScale != value) {
+ _textScale = value;
+ notifyListeners();
+ if (value == null) {
+ Store.sp.remove(StoreKeys.TEXT_SCALE);
+ } else {
+ Store.sp.setDouble(StoreKeys.TEXT_SCALE, value);
+ }
+ }
+ }
}=
\ No newline at end of file
M lib/pages/article_page.dart => lib/pages/article_page.dart +2 -1
@@ 53,7 53,8 @@ class ArticlePageState extends State<ArticlePage> {
Future<NavigationDecision> _onNavigate(NavigationRequest request) async {
if (navigated && request.isForMainFrame) {
- await launch(request.url);
+ final internal = Global.globalModel.inAppBrowser;
+ await launch(request.url, forceSafariVC: internal, forceWebView: internal);
return NavigationDecision.prevent;
} else {
return NavigationDecision.navigate;
M lib/pages/group_list_page.dart => lib/pages/group_list_page.dart +1 -1
@@ 43,7 43,7 @@ class _GroupListPageState extends State<GroupListPage> {
return SliverToBoxAdapter(child: MyListTile(
title: Text(S.of(context).allSubscriptions),
trailing: count > 0 ? Badge(count) : null,
- onTap: () { Navigator.of(context).pop(List<String>()); },
+ onTap: () { Navigator.of(context).pop(List<String>.empty()); },
background: CupertinoColors.systemBackground,
));
},
M lib/pages/settings/general_page.dart => lib/pages/settings/general_page.dart +47 -2
@@ 16,6 16,7 @@ class GeneralPage extends StatefulWidget {
class _GeneralPageState extends State<GeneralPage> {
bool _clearingCache = false;
+ double textScale;
void _clearCache() async {
setState(() { _clearingCache = true; });
@@ 32,9 33,41 @@ class _GeneralPageState extends State<GeneralPage> {
),
child: Consumer<GlobalModel>(
builder: (context, globalModel, child) {
+ final useSystemTextScale = globalModel.textScale == null;
+ final textScaleItems = ListTileGroup([
+ MyListTile(
+ title: Text(S.of(context).followSystem),
+ trailing: CupertinoSwitch(
+ value: useSystemTextScale,
+ onChanged: (v) {
+ textScale = null;
+ globalModel.textScale = v ? null : 1;
+ },
+ ),
+ trailingChevron: false,
+ withDivider: !useSystemTextScale,
+ ),
+ if (!useSystemTextScale) MyListTile(
+ title: Expanded(child: CupertinoSlider(
+ min: 0.5,
+ max: 1.5,
+ divisions: 8,
+ value: textScale ?? globalModel.textScale,
+ onChanged: (v) {
+ setState(() { textScale = v; });
+ },
+ onChangeEnd: (v) {
+ textScale = null;
+ globalModel.textScale = v;
+ },
+ )),
+ trailingChevron: false,
+ withDivider: false,
+ ),
+ ], title: S.of(context).fontSize);
final syncItems = ListTileGroup([
MyListTile(
- title: Text(S.of(context).onStart),
+ title: Text(S.of(context).syncOnStart),
trailing: CupertinoSwitch(
value: globalModel.syncOnStart,
onChanged: (v) {
@@ 43,9 76,20 @@ class _GeneralPageState extends State<GeneralPage> {
},
),
trailingChevron: false,
+ ),
+ MyListTile(
+ title: Text(S.of(context).inAppBrowser),
+ trailing: CupertinoSwitch(
+ value: globalModel.inAppBrowser,
+ onChanged: (v) {
+ globalModel.inAppBrowser = v;
+ setState(() {});
+ },
+ ),
+ trailingChevron: false,
withDivider: false,
),
- ], title: S.of(context).sync);
+ ], title: S.of(context).preferences);
final storageItems = ListTileGroup([
MyListTile(
title: Text(S.of(context).clearCache),
@@ 97,6 141,7 @@ class _GeneralPageState extends State<GeneralPage> {
return ListView(
children: [
syncItems,
+ textScaleItems,
storageItems,
themeItems,
localeItems,
M lib/pages/settings/services/feedbin_page.dart => lib/pages/settings/services/feedbin_page.dart +9 -1
@@ 1,3 1,5 @@
+import 'dart:io';
+
import 'package:fluent_reader_lite/components/list_tile_group.dart';
import 'package:fluent_reader_lite/components/my_list_tile.dart';
import 'package:fluent_reader_lite/generated/l10n.dart';
@@ 123,6 125,7 @@ class _FeedbinPageState extends State<FeedbinPage> {
DialogWidget.progress(style: DialogStyle.cupertino),
);
await Global.syncModel.removeService();
+ _validating = false;
DialogHelper().hide(context);
final navigator = Navigator.of(context);
while (navigator.canPop()) navigator.pop();
@@ 222,7 225,7 @@ class _FeedbinPageState extends State<FeedbinPage> {
], title: "");
},
);
- return CupertinoPageScaffold(
+ final page = CupertinoPageScaffold(
backgroundColor: MyColors.background,
navigationBar: CupertinoNavigationBar(
middle: Text("Feedbin"),
@@ 234,5 237,10 @@ class _FeedbinPageState extends State<FeedbinPage> {
if (Global.service != null) logOutButton,
]),
);
+ if (Platform.isAndroid) {
+ return WillPopScope(child: page, onWillPop: () async => !_validating);
+ } else {
+ return page;
+ }
}
}
M lib/pages/settings/services/fever_page.dart => lib/pages/settings/services/fever_page.dart +8 -1
@@ 1,4 1,5 @@
import 'dart:convert';
+import 'dart:io';
import 'package:crypto/crypto.dart';
import 'package:fluent_reader_lite/components/list_tile_group.dart';
@@ 126,6 127,7 @@ class _FeverPageState extends State<FeverPage> {
DialogWidget.progress(style: DialogStyle.cupertino),
);
await Global.syncModel.removeService();
+ _validating = false;
DialogHelper().hide(context);
final navigator = Navigator.of(context);
while (navigator.canPop()) navigator.pop();
@@ 223,7 225,7 @@ class _FeverPageState extends State<FeverPage> {
], title: "");
},
);
- return CupertinoPageScaffold(
+ final page = CupertinoPageScaffold(
backgroundColor: MyColors.background,
navigationBar: CupertinoNavigationBar(
middle: Text("Fever API"),
@@ 235,5 237,10 @@ class _FeverPageState extends State<FeverPage> {
if (Global.service != null) logOutButton,
]),
);
+ if (Platform.isAndroid) {
+ return WillPopScope(child: page, onWillPop: () async => !_validating);
+ } else {
+ return page;
+ }
}
}
M lib/utils/store.dart => lib/utils/store.dart +2 -0
@@ 12,6 12,8 @@ abstract class StoreKeys {
static const LOCALE = "locale";
static const KEEP_ITEMS_DAYS = "keepItemsD";
static const SYNC_ON_START = "syncOnStart";
+ static const IN_APP_BROWSER = "inAppBrowser";
+ static const TEXT_SCALE = "textScale";
// Feed preferences
static const FEED_FILTER_ALL = "feedFilterA";