From be23c4fe68b459cb909ccb5103ee090b1e99ef13 Mon Sep 17 00:00:00 2001 From: Yoshiro_fan Date: Sun, 26 Oct 2025 16:30:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E5=AE=8C=E6=88=90=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/translation.json | 8 + lib/foundation/image_favorites.dart | 2 +- lib/pages/favorites/favorites_page.dart | 1 + lib/pages/favorites/local_favorites_page.dart | 153 ++++++++++++++++-- lib/pages/reader/reader.dart | 3 + 5 files changed, 154 insertions(+), 13 deletions(-) diff --git a/assets/translation.json b/assets/translation.json index b3cb873..17271c6 100644 --- a/assets/translation.json +++ b/assets/translation.json @@ -47,6 +47,7 @@ "Move to folder": "移动到文件夹", "Copy to folder": "复制到文件夹", "Delete Comic": "删除漫画", + "Jump to Detail": "跳转详情", "Delete @c comics?": "删除 @c 本漫画?", "Add comic source": "添加漫画源", "Delete comic source '@n' ?": "删除漫画源 '@n' ?", @@ -69,6 +70,9 @@ "Next": "前进", "Login with webview": "通过网页登录", "Read": "阅读", + "Completed": "已完成", + "UnCompleted": "未完成", + "Filter reading status": "过滤阅读状态", "Download": "下载", "Favorite": "收藏", "Comments": "评论", @@ -464,6 +468,7 @@ "Move": "移動", "Move to folder": "移動到資料夾", "Copy to folder": "複製到資料夾", + "Jump to Detail": "跳轉詳情​​", "Delete Comic": "刪除漫畫", "Delete @c comics?": "刪除 @c 本漫畫?", "Add comic source": "添加漫畫源", @@ -487,6 +492,9 @@ "Next": "前進", "Login with webview": "透過網頁登入", "Read": "閱讀", + "Completed": "已完成", + "UnCompleted": "未完成", + "Filter reading status": "過濾閱讀狀態", "Download": "下載", "Favorite": "收藏", "Comments": "評論", diff --git a/lib/foundation/image_favorites.dart b/lib/foundation/image_favorites.dart index 61a9b76..64ff8fd 100644 --- a/lib/foundation/image_favorites.dart +++ b/lib/foundation/image_favorites.dart @@ -441,7 +441,7 @@ class ImageFavoriteManager with ChangeNotifier { for (var comic in comics) { count += comic.images.length; for (var tag in comic.tags) { - String finalTag = tag; + String finalTag = tag.split(":").last; tagCount[finalTag] = (tagCount[finalTag] ?? 0) + 1; } diff --git a/lib/pages/favorites/favorites_page.dart b/lib/pages/favorites/favorites_page.dart index d44235b..0987fff 100644 --- a/lib/pages/favorites/favorites_page.dart +++ b/lib/pages/favorites/favorites_page.dart @@ -11,6 +11,7 @@ import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/comic_type.dart'; import 'package:venera/foundation/consts.dart'; import 'package:venera/foundation/favorites.dart'; +import 'package:venera/foundation/history.dart'; import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/log.dart'; import 'package:venera/foundation/res.dart'; diff --git a/lib/pages/favorites/local_favorites_page.dart b/lib/pages/favorites/local_favorites_page.dart index 3002158..65ab729 100644 --- a/lib/pages/favorites/local_favorites_page.dart +++ b/lib/pages/favorites/local_favorites_page.dart @@ -43,6 +43,8 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { bool isLoading = false; + late String readFilterSelect; + var searchResults = []; void updateSearchResult() { @@ -104,6 +106,19 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { setState(() {}); } + List filterComics(List curComics) { + return curComics.where((comic) { + var history = + HistoryManager().find(comic.id, ComicType(comic.sourceKey.hashCode)); + if (readFilterSelect == "UnCompleted") { + return history == null || history.page != history.maxPage; + } else if (readFilterSelect == "Completed") { + return history != null && history.page == history.maxPage; + } + return true; + }).toList(); + } + bool matchKeyword(String keyword, FavoriteItem comic) { var list = keyword.split(" "); for (var k in list) { @@ -152,6 +167,8 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { @override void initState() { + readFilterSelect = appdata.implicitData["local_favorites_read_filter"] ?? + readFilterList[0]; favPage = context.findAncestorStateOfType<_FavoritesPageState>()!; if (!isAllFolder) { var (a, b) = LocalFavoritesManager().findLinked(widget.folder); @@ -320,6 +337,31 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { }), ), ), + Tooltip( + message: "Filter".tl, + child: IconButton( + icon: const Icon(Icons.sort_rounded), + color: readFilterSelect != readFilterList[0] + ? context.colorScheme.primaryContainer + : null, + onPressed: () { + showDialog( + context: context, + builder: (context) { + return _LocalFavoritesFilterDialog( + initReadFilterSelect: readFilterSelect, + updateConfig: (readFilter) { + setState(() { + readFilterSelect = readFilter; + }); + updateComics(); + }, + ); + }, + ); + }, + ), + ), Tooltip( message: "Search".tl, child: IconButton( @@ -454,15 +496,15 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { actions: [ MenuButton(entries: [ if (!isAllFolder) - MenuEntry( - icon: Icons.drive_file_move, - text: "Move to folder".tl, - onClick: () => favoriteOption('move')), + MenuEntry( + icon: Icons.drive_file_move, + text: "Move to folder".tl, + onClick: () => favoriteOption('move')), if (!isAllFolder) - MenuEntry( - icon: Icons.copy, - text: "Copy to folder".tl, - onClick: () => favoriteOption('add')), + MenuEntry( + icon: Icons.copy, + text: "Copy to folder".tl, + onClick: () => favoriteOption('add')), MenuEntry( icon: Icons.select_all, text: "Select All".tl, @@ -519,9 +561,21 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { onClick: () { final c = selectedComics.keys.first as FavoriteItem; App.rootContext.to(() => ReaderWithLoading( - id: c.id, - sourceKey: c.sourceKey, - )); + id: c.id, + sourceKey: c.sourceKey, + )); + }, + ), + if (selectedComics.length == 1) + MenuEntry( + icon: Icons.arrow_forward_ios, + text: "Jump to Detail".tl, + onClick: () { + final c = selectedComics.keys.first as FavoriteItem; + App.mainNavigatorKey?.currentContext?.to(() => ComicPage( + id: c.id, + sourceKey: c.sourceKey, + )); }, ), ]), @@ -568,7 +622,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { ) else SliverGridComics( - comics: searchMode ? searchResults : comics, + comics: searchMode ? searchResults : filterComics(comics), selections: selectedComics, menuBuilder: (c) { return [ @@ -1075,3 +1129,78 @@ class _SelectUpdatePageNumState extends State<_SelectUpdatePageNum> { ); } } + +class _LocalFavoritesFilterDialog extends StatefulWidget { + const _LocalFavoritesFilterDialog({ + required this.initReadFilterSelect, + required this.updateConfig, + }); + + final String initReadFilterSelect; + final Function updateConfig; + + @override + State<_LocalFavoritesFilterDialog> createState() => + _LocalFavoritesFilterDialogState(); +} + +const readFilterList = ['All', 'UnCompleted', 'Completed']; + +class _LocalFavoritesFilterDialogState + extends State<_LocalFavoritesFilterDialog> { + List optionTypes = ['Filter']; + late var readFilter = widget.initReadFilterSelect; + @override + Widget build(BuildContext context) { + Widget tabBar = Material( + borderRadius: BorderRadius.circular(8), + child: AppTabBar( + key: PageStorageKey(optionTypes), + tabs: optionTypes.map((e) => Tab(text: e.tl, key: Key(e))).toList(), + ), + ).paddingTop(context.padding.top); + return ContentDialog( + content: DefaultTabController( + length: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + tabBar, + TabViewBody(children: [ + Column( + children: [ + ListTile( + title: Text("Filter reading status".tl), + trailing: Select( + current: readFilter.tl, + values: readFilterList.map((e) => e.tl).toList(), + minWidth: 64, + onTap: (index) { + setState(() { + readFilter = readFilterList[index]; + }); + }, + ), + ) + ], + ) + ]), + ], + ), + ), + actions: [ + FilledButton( + onPressed: () { + appdata.implicitData["local_favorites_read_filter"] = readFilter; + appdata.writeImplicitData(); + if (mounted) { + Navigator.pop(context); + widget.updateConfig(readFilter); + } + }, + child: Text("Confirm".tl), + ), + ], + ); + } +} diff --git a/lib/pages/reader/reader.dart b/lib/pages/reader/reader.dart index 0f17b64..2e29775 100644 --- a/lib/pages/reader/reader.dart +++ b/lib/pages/reader/reader.dart @@ -163,6 +163,9 @@ class _ReaderState extends State } if (widget.initialPage != null) { page = widget.initialPage!; + if (page < 1) { + page = 1; + } } // mode = ReaderMode.fromKey(appdata.settings['readerMode']); mode = ReaderMode.fromKey(appdata.settings.getReaderSetting(cid, type.sourceKey, 'readerMode'));