quick favorite

This commit is contained in:
2024-11-10 15:57:52 +08:00
parent 4f4411fcc3
commit aa415f201e
6 changed files with 123 additions and 17 deletions

View File

@@ -185,7 +185,10 @@
"Saved": "已保存", "Saved": "已保存",
"Sync Data": "同步数据", "Sync Data": "同步数据",
"Syncing Data": "正在同步数据", "Syncing Data": "正在同步数据",
"Data Sync": "数据同步" "Data Sync": "数据同步",
"Quick Favorite": "快速收藏",
"Long press on the favorite button to quickly add to this folder": "长按收藏按钮快速添加到这个文件夹",
"Added": "已添加"
}, },
"zh_TW": { "zh_TW": {
"Home": "首頁", "Home": "首頁",
@@ -373,6 +376,9 @@
"Saved": "已保存", "Saved": "已保存",
"Sync Data": "同步數據", "Sync Data": "同步數據",
"Syncing Data": "正在同步數據", "Syncing Data": "正在同步數據",
"Data Sync": "數據同步" "Data Sync": "數據同步",
"Quick Favorite": "快速收藏",
"Long press on the favorite button to quickly add to this folder": "長按收藏按鈕快速添加到這個文件夾",
"Added": "已添加"
} }
} }

View File

@@ -116,6 +116,7 @@ class _Settings with ChangeNotifier {
'limitImageWidth': true, 'limitImageWidth': true,
'webdav': [], // empty means not configured 'webdav': [], // empty means not configured
'dataVersion': 0, 'dataVersion': 0,
'quickFavorite': null,
}; };
operator [](String key) { operator [](String key) {

View File

@@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:venera/components/components.dart'; import 'package:venera/components/components.dart';
import 'package:venera/foundation/app.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_source/comic_source.dart';
import 'package:venera/foundation/comic_type.dart'; import 'package:venera/foundation/comic_type.dart';
import 'package:venera/foundation/consts.dart'; import 'package:venera/foundation/consts.dart';
@@ -282,6 +283,7 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
isActive: isFavorite || isAddToLocalFav, isActive: isFavorite || isAddToLocalFav,
text: 'Favorite'.tl, text: 'Favorite'.tl,
onPressed: openFavPanel, onPressed: openFavPanel,
onLongPressed: quickFavorite,
iconColor: context.useTextColor(Colors.purple), iconColor: context.useTextColor(Colors.purple),
), ),
if (comicSource.commentsLoader != null) if (comicSource.commentsLoader != null)
@@ -538,12 +540,22 @@ abstract mixin class _ComicPageActions {
bool isFavorite = false; bool isFavorite = false;
void openFavPanel() { FavoriteItem _toFavoriteItem() {
var tags = <String>[]; var tags = <String>[];
for (var e in comic.tags.entries) { for (var e in comic.tags.entries) {
tags.addAll(e.value.map((tag) => '${e.key}:$tag')); 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( showSideBar(
App.rootContext, App.rootContext,
_FavoritePanel( _FavoritePanel(
@@ -555,18 +567,25 @@ abstract mixin class _ComicPageActions {
isAddToLocalFav = local ?? isAddToLocalFav; isAddToLocalFav = local ?? isAddToLocalFav;
update(); update();
}, },
favoriteItem: FavoriteItem( favoriteItem: _toFavoriteItem(),
id: comic.id,
name: comic.title,
coverPath: comic.cover,
author: comic.subTitle ?? comic.uploader ?? '',
type: comic.comicType,
tags: tags,
),
), ),
); );
} }
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() { void share() {
var text = comic.title; var text = comic.title;
if (comic.url != null) { if (comic.url != null) {
@@ -800,6 +819,7 @@ class _ActionButton extends StatelessWidget {
required this.icon, required this.icon,
required this.text, required this.text,
required this.onPressed, required this.onPressed,
this.onLongPressed,
this.activeIcon, this.activeIcon,
this.isActive, this.isActive,
this.isLoading, this.isLoading,
@@ -820,6 +840,8 @@ class _ActionButton extends StatelessWidget {
final Color? iconColor; final Color? iconColor;
final void Function()? onLongPressed;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@@ -837,6 +859,7 @@ class _ActionButton extends StatelessWidget {
onPressed(); onPressed();
} }
}, },
onLongPress: onLongPressed,
borderRadius: BorderRadius.circular(18), borderRadius: BorderRadius.circular(18),
child: IconTheme.merge( child: IconTheme.merge(
data: IconThemeData(size: 20, color: iconColor), data: IconThemeData(size: 20, color: iconColor),

View File

@@ -24,12 +24,20 @@ class _LocalFavoritesSettingsState extends State<LocalFavoritesSettings> {
SelectSetting( SelectSetting(
title: "Move favorite after reading".tl, title: "Move favorite after reading".tl,
settingKey: "moveFavoriteAfterRead", settingKey: "moveFavoriteAfterRead",
optionTranslation: { optionTranslation: const {
"none": "None", "none": "None",
"end": "End", "end": "End",
"start": "Start", "start": "Start",
}, },
).toSliver(), ).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(),
], ],
); );
} }

View File

@@ -49,6 +49,7 @@ class SelectSetting extends StatelessWidget {
required this.settingKey, required this.settingKey,
required this.optionTranslation, required this.optionTranslation,
this.onChanged, this.onChanged,
this.help,
}); });
final String title; final String title;
@@ -59,6 +60,8 @@ class SelectSetting extends StatelessWidget {
final VoidCallback? onChanged; final VoidCallback? onChanged;
final String? help;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return SizedBox(
@@ -71,6 +74,7 @@ class SelectSetting extends StatelessWidget {
settingKey: settingKey, settingKey: settingKey,
optionTranslation: optionTranslation, optionTranslation: optionTranslation,
onChanged: onChanged, onChanged: onChanged,
help: help,
); );
} else { } else {
return _EndSelectorSelectSetting( return _EndSelectorSelectSetting(
@@ -78,6 +82,7 @@ class SelectSetting extends StatelessWidget {
settingKey: settingKey, settingKey: settingKey,
optionTranslation: optionTranslation, optionTranslation: optionTranslation,
onChanged: onChanged, onChanged: onChanged,
help: help,
); );
} }
}, },
@@ -92,6 +97,7 @@ class _DoubleLineSelectSettings extends StatefulWidget {
required this.settingKey, required this.settingKey,
required this.optionTranslation, required this.optionTranslation,
this.onChanged, this.onChanged,
this.help,
}); });
final String title; final String title;
@@ -102,6 +108,8 @@ class _DoubleLineSelectSettings extends StatefulWidget {
final VoidCallback? onChanged; final VoidCallback? onChanged;
final String? help;
@override @override
State<_DoubleLineSelectSettings> createState() => State<_DoubleLineSelectSettings> createState() =>
_DoubleLineSelectSettingsState(); _DoubleLineSelectSettingsState();
@@ -111,9 +119,37 @@ class _DoubleLineSelectSettingsState extends State<_DoubleLineSelectSettings> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
title: Text(widget.title), title: Row(
subtitle: children: [
Text(widget.optionTranslation[appdata.settings[widget.settingKey]]!), 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), trailing: const Icon(Icons.arrow_drop_down),
onTap: () { onTap: () {
var renderBox = context.findRenderObject() as RenderBox; var renderBox = context.findRenderObject() as RenderBox;
@@ -156,6 +192,7 @@ class _EndSelectorSelectSetting extends StatefulWidget {
required this.settingKey, required this.settingKey,
required this.optionTranslation, required this.optionTranslation,
this.onChanged, this.onChanged,
this.help,
}); });
final String title; final String title;
@@ -166,6 +203,8 @@ class _EndSelectorSelectSetting extends StatefulWidget {
final VoidCallback? onChanged; final VoidCallback? onChanged;
final String? help;
@override @override
State<_EndSelectorSelectSetting> createState() => State<_EndSelectorSelectSetting> createState() =>
_EndSelectorSelectSettingState(); _EndSelectorSelectSettingState();
@@ -176,10 +215,38 @@ class _EndSelectorSelectSettingState extends State<_EndSelectorSelectSetting> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var options = widget.optionTranslation; var options = widget.optionTranslation;
return ListTile( 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( trailing: Select(
current: options[appdata.settings[widget.settingKey]]!, current: options[appdata.settings[widget.settingKey]],
values: options.values.toList(), values: options.values.toList(),
minWidth: 64,
onTap: (index) { onTap: (index) {
setState(() { setState(() {
appdata.settings[widget.settingKey] = options.keys.elementAt(index); appdata.settings[widget.settingKey] = options.keys.elementAt(index);

View File

@@ -11,6 +11,7 @@ import 'package:venera/foundation/appdata.dart';
import 'package:venera/foundation/cache_manager.dart'; import 'package:venera/foundation/cache_manager.dart';
import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/comic_source/comic_source.dart';
import 'package:venera/foundation/consts.dart'; import 'package:venera/foundation/consts.dart';
import 'package:venera/foundation/favorites.dart';
import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/local.dart';
import 'package:venera/foundation/log.dart'; import 'package:venera/foundation/log.dart';
import 'package:venera/network/app_dio.dart'; import 'package:venera/network/app_dio.dart';