From aa415f201e165ba8229db38a6844df64d356afbf Mon Sep 17 00:00:00 2001 From: nyne Date: Sun, 10 Nov 2024 15:57:52 +0800 Subject: [PATCH] quick favorite --- assets/translation.json | 10 ++- lib/foundation/appdata.dart | 1 + lib/pages/comic_page.dart | 41 +++++++++--- lib/pages/settings/local_favorites.dart | 10 ++- lib/pages/settings/setting_components.dart | 77 ++++++++++++++++++++-- lib/pages/settings/settings_page.dart | 1 + 6 files changed, 123 insertions(+), 17 deletions(-) diff --git a/assets/translation.json b/assets/translation.json index cfcb64d..ab09880 100644 --- a/assets/translation.json +++ b/assets/translation.json @@ -185,7 +185,10 @@ "Saved": "已保存", "Sync Data": "同步数据", "Syncing Data": "正在同步数据", - "Data Sync": "数据同步" + "Data Sync": "数据同步", + "Quick Favorite": "快速收藏", + "Long press on the favorite button to quickly add to this folder": "长按收藏按钮快速添加到这个文件夹", + "Added": "已添加" }, "zh_TW": { "Home": "首頁", @@ -373,6 +376,9 @@ "Saved": "已保存", "Sync Data": "同步數據", "Syncing Data": "正在同步數據", - "Data Sync": "數據同步" + "Data Sync": "數據同步", + "Quick Favorite": "快速收藏", + "Long press on the favorite button to quickly add to this folder": "長按收藏按鈕快速添加到這個文件夾", + "Added": "已添加" } } \ No newline at end of file diff --git a/lib/foundation/appdata.dart b/lib/foundation/appdata.dart index 1d26838..e72bdf3 100644 --- a/lib/foundation/appdata.dart +++ b/lib/foundation/appdata.dart @@ -116,6 +116,7 @@ class _Settings with ChangeNotifier { 'limitImageWidth': true, 'webdav': [], // empty means not configured 'dataVersion': 0, + 'quickFavorite': null, }; operator [](String key) { diff --git a/lib/pages/comic_page.dart b/lib/pages/comic_page.dart index 3488b66..62b086b 100644 --- a/lib/pages/comic_page.dart +++ b/lib/pages/comic_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:venera/components/components.dart'; import 'package:venera/foundation/app.dart'; +import 'package:venera/foundation/appdata.dart'; import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/comic_type.dart'; import 'package:venera/foundation/consts.dart'; @@ -282,6 +283,7 @@ class _ComicPageState extends LoadingState isActive: isFavorite || isAddToLocalFav, text: 'Favorite'.tl, onPressed: openFavPanel, + onLongPressed: quickFavorite, iconColor: context.useTextColor(Colors.purple), ), if (comicSource.commentsLoader != null) @@ -538,12 +540,22 @@ abstract mixin class _ComicPageActions { bool isFavorite = false; - void openFavPanel() { + FavoriteItem _toFavoriteItem() { var tags = []; for (var e in comic.tags.entries) { tags.addAll(e.value.map((tag) => '${e.key}:$tag')); } + return FavoriteItem( + id: comic.id, + name: comic.title, + coverPath: comic.cover, + author: comic.subTitle ?? comic.uploader ?? '', + type: comic.comicType, + tags: tags, + ); + } + void openFavPanel() { showSideBar( App.rootContext, _FavoritePanel( @@ -555,18 +567,25 @@ abstract mixin class _ComicPageActions { isAddToLocalFav = local ?? isAddToLocalFav; update(); }, - favoriteItem: FavoriteItem( - id: comic.id, - name: comic.title, - coverPath: comic.cover, - author: comic.subTitle ?? comic.uploader ?? '', - type: comic.comicType, - tags: tags, - ), + favoriteItem: _toFavoriteItem(), ), ); } + void quickFavorite() { + var folder = appdata.settings['quickFavorite']; + if(folder is! String) { + return; + } + LocalFavoritesManager().addComic( + folder, + _toFavoriteItem(), + ); + isAddToLocalFav = true; + update(); + App.rootContext.showMessage(message: "Added".tl); + } + void share() { var text = comic.title; if (comic.url != null) { @@ -800,6 +819,7 @@ class _ActionButton extends StatelessWidget { required this.icon, required this.text, required this.onPressed, + this.onLongPressed, this.activeIcon, this.isActive, this.isLoading, @@ -820,6 +840,8 @@ class _ActionButton extends StatelessWidget { final Color? iconColor; + final void Function()? onLongPressed; + @override Widget build(BuildContext context) { return Container( @@ -837,6 +859,7 @@ class _ActionButton extends StatelessWidget { onPressed(); } }, + onLongPress: onLongPressed, borderRadius: BorderRadius.circular(18), child: IconTheme.merge( data: IconThemeData(size: 20, color: iconColor), diff --git a/lib/pages/settings/local_favorites.dart b/lib/pages/settings/local_favorites.dart index ac056e5..9cbce52 100644 --- a/lib/pages/settings/local_favorites.dart +++ b/lib/pages/settings/local_favorites.dart @@ -24,12 +24,20 @@ class _LocalFavoritesSettingsState extends State { SelectSetting( title: "Move favorite after reading".tl, settingKey: "moveFavoriteAfterRead", - optionTranslation: { + optionTranslation: const { "none": "None", "end": "End", "start": "Start", }, ).toSliver(), + SelectSetting( + title: "Quick Favorite".tl, + settingKey: "quickFavorite", + help: "Long press on the favorite button to quickly add to this folder".tl, + optionTranslation: { + for (var e in LocalFavoritesManager().folderNames) e: e + }, + ).toSliver(), ], ); } diff --git a/lib/pages/settings/setting_components.dart b/lib/pages/settings/setting_components.dart index 9a95270..ee14ddc 100644 --- a/lib/pages/settings/setting_components.dart +++ b/lib/pages/settings/setting_components.dart @@ -49,6 +49,7 @@ class SelectSetting extends StatelessWidget { required this.settingKey, required this.optionTranslation, this.onChanged, + this.help, }); final String title; @@ -59,6 +60,8 @@ class SelectSetting extends StatelessWidget { final VoidCallback? onChanged; + final String? help; + @override Widget build(BuildContext context) { return SizedBox( @@ -71,6 +74,7 @@ class SelectSetting extends StatelessWidget { settingKey: settingKey, optionTranslation: optionTranslation, onChanged: onChanged, + help: help, ); } else { return _EndSelectorSelectSetting( @@ -78,6 +82,7 @@ class SelectSetting extends StatelessWidget { settingKey: settingKey, optionTranslation: optionTranslation, onChanged: onChanged, + help: help, ); } }, @@ -92,6 +97,7 @@ class _DoubleLineSelectSettings extends StatefulWidget { required this.settingKey, required this.optionTranslation, this.onChanged, + this.help, }); final String title; @@ -102,6 +108,8 @@ class _DoubleLineSelectSettings extends StatefulWidget { final VoidCallback? onChanged; + final String? help; + @override State<_DoubleLineSelectSettings> createState() => _DoubleLineSelectSettingsState(); @@ -111,9 +119,37 @@ class _DoubleLineSelectSettingsState extends State<_DoubleLineSelectSettings> { @override Widget build(BuildContext context) { return ListTile( - title: Text(widget.title), - subtitle: - Text(widget.optionTranslation[appdata.settings[widget.settingKey]]!), + title: Row( + children: [ + Text(widget.title), + const SizedBox(width: 4), + if (widget.help != null) + Button.icon( + size: 18, + icon: const Icon(Icons.help_outline), + onPressed: () { + showDialog( + context: context, + builder: (context) { + return ContentDialog( + title: "Help".tl, + content: Text(widget.help!).paddingHorizontal(16).fixWidth(double.infinity), + actions: [ + Button.filled( + onPressed: context.pop, + child: Text("OK".tl), + ), + ], + ); + }, + ); + }, + ), + ], + ), + subtitle: Text( + widget.optionTranslation[appdata.settings[widget.settingKey]] ?? + "None"), trailing: const Icon(Icons.arrow_drop_down), onTap: () { var renderBox = context.findRenderObject() as RenderBox; @@ -156,6 +192,7 @@ class _EndSelectorSelectSetting extends StatefulWidget { required this.settingKey, required this.optionTranslation, this.onChanged, + this.help, }); final String title; @@ -166,6 +203,8 @@ class _EndSelectorSelectSetting extends StatefulWidget { final VoidCallback? onChanged; + final String? help; + @override State<_EndSelectorSelectSetting> createState() => _EndSelectorSelectSettingState(); @@ -176,10 +215,38 @@ class _EndSelectorSelectSettingState extends State<_EndSelectorSelectSetting> { Widget build(BuildContext context) { var options = widget.optionTranslation; return ListTile( - title: Text(widget.title), + title: Row( + children: [ + Text(widget.title), + const SizedBox(width: 4), + if (widget.help != null) + Button.icon( + size: 18, + icon: const Icon(Icons.help_outline), + onPressed: () { + showDialog( + context: context, + builder: (context) { + return ContentDialog( + title: "Help".tl, + content: Text(widget.help!).paddingHorizontal(16).fixWidth(double.infinity), + actions: [ + Button.filled( + onPressed: context.pop, + child: Text("OK".tl), + ), + ], + ); + }, + ); + }, + ), + ], + ), trailing: Select( - current: options[appdata.settings[widget.settingKey]]!, + current: options[appdata.settings[widget.settingKey]], values: options.values.toList(), + minWidth: 64, onTap: (index) { setState(() { appdata.settings[widget.settingKey] = options.keys.elementAt(index); diff --git a/lib/pages/settings/settings_page.dart b/lib/pages/settings/settings_page.dart index d009d89..4066c61 100644 --- a/lib/pages/settings/settings_page.dart +++ b/lib/pages/settings/settings_page.dart @@ -11,6 +11,7 @@ import 'package:venera/foundation/appdata.dart'; import 'package:venera/foundation/cache_manager.dart'; import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/consts.dart'; +import 'package:venera/foundation/favorites.dart'; import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/log.dart'; import 'package:venera/network/app_dio.dart';