From 8864d2f827c4a6a9922ef8696be31c95ee7b1f24 Mon Sep 17 00:00:00 2001 From: Bruce Liu Date: Sun, 31 Jan 2021 12:18:32 +0800 Subject: [PATCH] add uncategorized group --- assets/article/article.css | 4 ++ lib/l10n/intl_en.arb | 4 +- lib/l10n/intl_zh.arb | 4 +- lib/models/groups_model.dart | 30 ++++++++++++ lib/pages/group_list_page.dart | 28 +++++++++-- lib/pages/settings/feed_page.dart | 68 +++++++++++++++++---------- lib/pages/subscription_list_page.dart | 6 +++ lib/utils/store.dart | 16 +++++++ 8 files changed, 128 insertions(+), 32 deletions(-) diff --git a/assets/article/article.css b/assets/article/article.css index 8572084..7298fcd 100644 --- a/assets/article/article.css +++ b/assets/article/article.css @@ -126,4 +126,8 @@ article ul, article menu, article dir { } article li { overflow: visible; +} +article pre { + white-space: pre-wrap; + word-break: break-all; } \ No newline at end of file diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index a31d735..2cadb8c 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -88,5 +88,7 @@ "retry": "Retry", "copy": "Copy", "errorLog": "Error log", - "unreadSourceTip": "You can long press on the title of this page to toggle between all and unread subscriptions." + "unreadSourceTip": "You can long press on the title of this page to toggle between all and unread subscriptions.", + "uncategorized": "Uncategorized", + "showUncategorized": "Show uncategorized" } \ No newline at end of file diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index 66032d0..88ad962 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -88,5 +88,7 @@ "retry": "重试", "copy": "复制", "errorLog": "错误日志", - "unreadSourceTip": "您可以长按此页面的标题来切换全部订阅源或仅未读订阅源。" + "unreadSourceTip": "您可以长按此页面的标题来切换全部订阅源或仅未读订阅源。", + "uncategorized": "未分组", + "showUncategorized": "显示“未分组”" } \ No newline at end of file diff --git a/lib/models/groups_model.dart b/lib/models/groups_model.dart index 683fc11..268e36a 100644 --- a/lib/models/groups_model.dart +++ b/lib/models/groups_model.dart @@ -1,8 +1,10 @@ +import 'package:fluent_reader_lite/utils/global.dart'; import 'package:fluent_reader_lite/utils/store.dart'; import 'package:flutter/cupertino.dart'; class GroupsModel with ChangeNotifier { Map> _groups = Store.getGroups(); + List uncategorized = Store.getUncategorized(); Map> get groups => _groups; set groups(Map> groups) { @@ -10,4 +12,32 @@ class GroupsModel with ChangeNotifier { notifyListeners(); Store.setGroups(groups); } + + void updateUncategorized({force: false}) { + if (uncategorized != null || force) { + final sids = Set.from( + Global.sourcesModel.getSources().map((s) => s.id) + ); + for (var group in _groups.values) { + for (var sid in group) { + sids.remove(sid); + } + } + uncategorized = sids.toList(); + Store.setUncategorized(uncategorized); + } + } + + bool get showUncategorized => uncategorized != null; + set showUncategorized(bool value) { + if (showUncategorized != value) { + if (value) { + updateUncategorized(force: true); + } else { + uncategorized = null; + Store.setUncategorized(null); + } + notifyListeners(); + } + } } \ No newline at end of file diff --git a/lib/pages/group_list_page.dart b/lib/pages/group_list_page.dart index 8910abd..6025182 100644 --- a/lib/pages/group_list_page.dart +++ b/lib/pages/group_list_page.dart @@ -18,6 +18,8 @@ class GroupListPage extends StatefulWidget { } class _GroupListPageState extends State { + static const List _uncategorizedIndicator = [null, null]; + int _unreadCount(Iterable sources) { return sources.fold(0, (c, s) => c + (s != null ? s.unreadCount : 0)); } @@ -55,27 +57,43 @@ class _GroupListPageState extends State { builder: (context, groupsModel, sourcesModel, child) { final groupNames = groupsModel.groups.keys.toList(); groupNames.sort(Utils.localStringCompare); + if (groupsModel.uncategorized != null) { + groupNames.insert(0, null); + } return SliverList( delegate: SliverChildBuilderDelegate((context, index) { - final groupName = groupNames[index]; + String groupName; + List group; + final isUncategorized = groupsModel.showUncategorized && index == 0; + if (isUncategorized) { + groupName = S.of(context).uncategorized; + group = groupsModel.uncategorized; + } else { + groupName = groupNames[index]; + group = groupsModel.groups[groupName]; + } final count = _unreadCount( - groupsModel.groups[groupName].map((sid) => sourcesModel.getSource(sid)) + group.map((sid) => sourcesModel.getSource(sid)) ); final tile = MyListTile( title: Flexible(child: Text(groupName, overflow: TextOverflow.ellipsis)), trailing: count > 0 ? Badge(count) : null, - onTap: () { Navigator.of(context).pop([groupName]); }, + onTap: () { + Navigator.of(context).pop( + isUncategorized ? _uncategorizedIndicator : [groupName] + ); + }, background: CupertinoColors.systemBackground, ); return Dismissible( - key: Key(groupName), + key: Key("$groupName$index"), child: tile, background: dismissBg, direction: DismissDirection.startToEnd, dismissThresholds: _dismissThresholds, confirmDismiss: (_) async { HapticFeedback.mediumImpact(); - Set sids = Set.from(groupsModel.groups[groupName]); + Set sids = Set.from(group); showCupertinoModalPopup( context: context, builder: (context) => MarkAllActionSheet(sids), diff --git a/lib/pages/settings/feed_page.dart b/lib/pages/settings/feed_page.dart index 1005a12..08c7fd4 100644 --- a/lib/pages/settings/feed_page.dart +++ b/lib/pages/settings/feed_page.dart @@ -2,6 +2,7 @@ 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'; import 'package:fluent_reader_lite/models/feeds_model.dart'; +import 'package:fluent_reader_lite/models/groups_model.dart'; import 'package:fluent_reader_lite/utils/colors.dart'; import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; @@ -56,35 +57,52 @@ class FeedPage extends StatelessWidget { ItemSwipeOption.OpenExternal: S.of(context).openExternal, ItemSwipeOption.OpenMenu: S.of(context).openMenu, }; - return ListView( - children: [ - ListTileGroup([ - MyListTile( - title: Text(S.of(context).showThumb), - trailing: CupertinoSwitch( - value: feedsModel.showThumb, - onChanged: (v) { feedsModel.showThumb = v; }, - ), - trailingChevron: false, - ), - MyListTile( - title: Text(S.of(context).showSnippet), - trailing: CupertinoSwitch( - value: feedsModel.showSnippet, - onChanged: (v) { feedsModel.showSnippet = v; }, - ), - trailingChevron: false, - ), - MyListTile( - title: Text(S.of(context).dimRead), + final preferences = ListTileGroup([ + MyListTile( + title: Text(S.of(context).showThumb), + trailing: CupertinoSwitch( + value: feedsModel.showThumb, + onChanged: (v) { feedsModel.showThumb = v; }, + ), + trailingChevron: false, + ), + MyListTile( + title: Text(S.of(context).showSnippet), + trailing: CupertinoSwitch( + value: feedsModel.showSnippet, + onChanged: (v) { feedsModel.showSnippet = v; }, + ), + trailingChevron: false, + ), + MyListTile( + title: Text(S.of(context).dimRead), + trailing: CupertinoSwitch( + value: feedsModel.dimRead, + onChanged: (v) { feedsModel.dimRead = v; }, + ), + trailingChevron: false, + withDivider: false, + ), + ], title: S.of(context).preferences); + final groups = ListTileGroup([ + Consumer( + builder: (context, groupsModel, child) { + return MyListTile( + title: Text(S.of(context).showUncategorized), trailing: CupertinoSwitch( - value: feedsModel.dimRead, - onChanged: (v) { feedsModel.dimRead = v; }, + value: groupsModel.showUncategorized, + onChanged: (v) { groupsModel.showUncategorized = v; }, ), trailingChevron: false, withDivider: false, - ), - ], title: S.of(context).preferences), + ); + }, + ), + ], title: S.of(context).groups); + return ListView( + children: [ + preferences, + groups, ListTileGroup([ MyListTile( title: Text(S.of(context).swipeRight), diff --git a/lib/pages/subscription_list_page.dart b/lib/pages/subscription_list_page.dart index 011c425..140f612 100644 --- a/lib/pages/subscription_list_page.dart +++ b/lib/pages/subscription_list_page.dart @@ -73,11 +73,17 @@ class _SubscriptionListPageState extends State { } if (!mounted) return; if (result != null) { + _onScrollTop(); if (result.length == 0) { setState(() { title = null; sids = null; }); + } else if (result.length > 1) { + setState(() { + title = S.of(context).uncategorized; + sids = Global.groupsModel.uncategorized; + }); } else { setState(() { title = result[0]; diff --git a/lib/utils/store.dart b/lib/utils/store.dart index 210b91b..6c118ca 100644 --- a/lib/utils/store.dart +++ b/lib/utils/store.dart @@ -7,6 +7,7 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class StoreKeys { static const GROUPS = "groups"; static const ERROR_LOG = "errorLog"; + static const UNCATEGORIZED = "uncategorized"; // General static const THEME = "theme"; @@ -92,6 +93,21 @@ class Store { sp.setString(StoreKeys.GROUPS, jsonEncode(groups)); } + static List getUncategorized() { + final stored = sp.getString(StoreKeys.UNCATEGORIZED); + if (stored == null) return null; + final parsed = jsonDecode(stored); + return List.castFrom(parsed); + } + + static void setUncategorized(List value) { + if (value == null) { + sp.remove(StoreKeys.UNCATEGORIZED); + } else { + sp.setString(StoreKeys.UNCATEGORIZED, jsonEncode(value)); + } + } + static int getArticleFontSize() { return sp.getInt(StoreKeys.ARTICLE_FONT_SIZE) ?? 16; } -- 2.38.5