From fa39bdf3eb518579f360a239fb2a9cc77dc13f0f Mon Sep 17 00:00:00 2001 From: nyne Date: Sun, 27 Oct 2024 16:03:46 +0800 Subject: [PATCH] fix deleting local comic, favorites --- lib/components/comic.dart | 5 +- lib/components/side_bar.dart | 2 +- lib/foundation/favorites.dart | 37 ++++++++++++- .../image_provider/local_favorite_image.dart | 53 +++++++++++++++++++ lib/foundation/local.dart | 10 +++- lib/pages/comments_page.dart | 1 + lib/pages/favorites/local_favorites_page.dart | 24 +++------ .../favorites/network_favorites_page.dart | 52 ++++++++++++------ lib/pages/local_comics_page.dart | 12 ++++- 9 files changed, 160 insertions(+), 36 deletions(-) create mode 100644 lib/foundation/image_provider/local_favorite_image.dart diff --git a/lib/components/comic.dart b/lib/components/comic.dart index 6cc1375..da0b708 100644 --- a/lib/components/comic.dart +++ b/lib/components/comic.dart @@ -50,7 +50,10 @@ class ComicTile extends StatelessWidget { MenuEntry( icon: Icons.chrome_reader_mode_outlined, text: 'Details'.tl, - onClick: _onTap, + onClick: () { + App.mainNavigatorKey?.currentContext + ?.to(() => ComicPage(id: comic.id, sourceKey: comic.sourceKey)); + }, ), MenuEntry( icon: Icons.copy, diff --git a/lib/components/side_bar.dart b/lib/components/side_bar.dart index 9431882..1afb208 100644 --- a/lib/components/side_bar.dart +++ b/lib/components/side_bar.dart @@ -180,7 +180,7 @@ class _SidebarBodyState extends State { width: 8, ), Tooltip( - message: "返回", + message: "Back".tl, child: IconButton( iconSize: 25, icon: const Icon(Icons.arrow_back), diff --git a/lib/foundation/favorites.dart b/lib/foundation/favorites.dart index 29c5cd7..bd81d46 100644 --- a/lib/foundation/favorites.dart +++ b/lib/foundation/favorites.dart @@ -3,6 +3,7 @@ import 'package:venera/foundation/appdata.dart'; import 'dart:io'; import 'app.dart'; +import 'comic_source/comic_source.dart'; import 'comic_type.dart'; String _getCurTime() { @@ -12,11 +13,13 @@ String _getCurTime() { .substring(0, 19); } -class FavoriteItem { +class FavoriteItem implements Comic { String name; String author; ComicType type; + @override List tags; + @override String id; String coverPath; String time = _getCurTime(); @@ -57,6 +60,38 @@ class FavoriteItem { } return s; } + + @override + String get cover => coverPath; + + @override + String get description => "$time | ${type.comicSource?.name ?? "Unknown"}"; + + @override + String? get favoriteId => null; + + @override + String? get language => null; + + @override + int? get maxPage => null; + + @override + String get sourceKey => type.comicSource?.key ?? "Unknown:${type.value}"; + + @override + double? get stars => null; + + @override + String? get subtitle => author; + + @override + String get title => name; + + @override + Map toJson() { + throw UnimplementedError(); + } } class FavoriteItemWithFolderInfo { diff --git a/lib/foundation/image_provider/local_favorite_image.dart b/lib/foundation/image_provider/local_favorite_image.dart new file mode 100644 index 0000000..f2d5ab4 --- /dev/null +++ b/lib/foundation/image_provider/local_favorite_image.dart @@ -0,0 +1,53 @@ +import 'dart:async' show Future, StreamController; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:venera/foundation/app.dart'; +import 'package:venera/foundation/comic_source/comic_source.dart'; +import 'package:venera/network/images.dart'; +import 'package:venera/utils/io.dart'; +import 'base_image_provider.dart'; +import 'local_favorite_image.dart' as image_provider; + +class LocalFavoriteImageProvider + extends BaseImageProvider { + /// Image provider for normal image. + const LocalFavoriteImageProvider(this.url, this.id, this.intKey); + + final String url; + + final String id; + + final int intKey; + + @override + Future load(StreamController chunkEvents) async { + var sourceKey = ComicSource.fromIntKey(intKey)?.key; + var fileName = key.hashCode.toString(); + var file = File(FilePath.join(App.dataPath, 'favorite_cover', fileName)); + if (await file.exists()) { + return await file.readAsBytes(); + } else { + await file.create(recursive: true); + } + await for (var progress in ImageDownloader.loadThumbnail(url, sourceKey)) { + chunkEvents.add(ImageChunkEvent( + cumulativeBytesLoaded: progress.currentBytes, + expectedTotalBytes: progress.totalBytes, + )); + if(progress.imageBytes != null) { + var data = progress.imageBytes!; + await file.writeAsBytes(data); + return data; + } + } + throw "Error: Empty response body."; + } + + @override + Future obtainKey(ImageConfiguration configuration) { + return SynchronousFuture(this); + } + + @override + String get key => id + intKey.toString(); +} diff --git a/lib/foundation/local.dart b/lib/foundation/local.dart index dff49bb..5255eff 100644 --- a/lib/foundation/local.dart +++ b/lib/foundation/local.dart @@ -26,7 +26,7 @@ class LocalComic with HistoryMixin implements Comic { @override final List tags; - /// name of the directory, which is in `LocalManager.path` + /// The name of the directory where the comic is stored final String directory; /// key: chapter id, value: chapter title @@ -143,6 +143,7 @@ class LocalManager with ChangeNotifier { late Database _db; + /// path to the directory where all the comics are stored late String path; // return error message if failed @@ -413,4 +414,11 @@ class LocalManager with ChangeNotifier { saveCurrentDownloadingTasks(); downloadingTasks.first.resume(); } + + void deleteComic(LocalComic c) { + var dir = Directory(FilePath.join(path, c.directory)); + dir.deleteSync(recursive: true); + remove(c.id, c.comicType); + notifyListeners(); + } } diff --git a/lib/pages/comments_page.dart b/lib/pages/comments_page.dart index cdbd268..cf4bd24 100644 --- a/lib/pages/comments_page.dart +++ b/lib/pages/comments_page.dart @@ -64,6 +64,7 @@ class _CommentsPageState extends State { @override Widget build(BuildContext context) { return Scaffold( + resizeToAvoidBottomInset: false, appBar: Appbar( title: Text("Comments".tl), ), diff --git a/lib/pages/favorites/local_favorites_page.dart b/lib/pages/favorites/local_favorites_page.dart index 877c7d2..24c9f7e 100644 --- a/lib/pages/favorites/local_favorites_page.dart +++ b/lib/pages/favorites/local_favorites_page.dart @@ -42,7 +42,12 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { ) : const SizedBox(), ), - title: Text(favPage.folder ?? "Unselected".tl), + title: GestureDetector( + onTap: context.width < _kTwoPanelChangeWidth + ? favPage.showFolderSelector + : null, + child: Text(favPage.folder ?? "Unselected".tl), + ), actions: [ MenuButton( entries: [ @@ -110,20 +115,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { ], ), SliverGridComics( - comics: comics.map((e) { - var comicSource = e.type.comicSource; - return Comic( - e.name, - e.coverPath, - e.id, - e.author, - e.tags, - "${e.time} | ${comicSource?.name ?? "Unknown"}", - comicSource?.key ?? "Unknown", - null, - null, - ); - }).toList(), + comics: comics, menuBuilder: (c) { return [ MenuEntry( @@ -138,7 +130,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> { LocalFavoritesManager().deleteComicWithId( widget.folder, c.id, - ComicType(c.sourceKey.hashCode), + (c as FavoriteItem).type, ); updateComics(); }, diff --git a/lib/pages/favorites/network_favorites_page.dart b/lib/pages/favorites/network_favorites_page.dart index c29c694..d08d1fc 100644 --- a/lib/pages/favorites/network_favorites_page.dart +++ b/lib/pages/favorites/network_favorites_page.dart @@ -83,6 +83,12 @@ class _NormalFavoritePage extends StatefulWidget { class _NormalFavoritePageState extends State<_NormalFavoritePage> { final comicListKey = GlobalKey(); + void showFolders() { + context + .findAncestorStateOfType<_FavoritesPageState>()! + .showFolderSelector(); + } + @override Widget build(BuildContext context) { return ComicList( @@ -94,13 +100,14 @@ class _NormalFavoritePageState extends State<_NormalFavoritePage> { ? IconButton( icon: const Icon(Icons.menu), color: context.colorScheme.primary, - onPressed: context - .findAncestorStateOfType<_FavoritesPageState>()! - .showFolderSelector, + onPressed: showFolders, ) : null, ), - title: Text(widget.data.title), + title: GestureDetector( + onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null, + child: Text(widget.data.title), + ), ), errorLeading: Appbar( leading: Tooltip( @@ -115,10 +122,17 @@ class _NormalFavoritePageState extends State<_NormalFavoritePage> { ) : null, ), - title: Text(widget.data.title), + title: GestureDetector( + onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null, + child: Text(widget.data.title), + ), ), - loadPage: widget.data.loadComic == null ? null : (i) => widget.data.loadComic!(i), - loadNext: widget.data.loadNext == null ? null : (next) => widget.data.loadNext!(next), + loadPage: widget.data.loadComic == null + ? null + : (i) => widget.data.loadComic!(i), + loadNext: widget.data.loadNext == null + ? null + : (next) => widget.data.loadNext!(next), menuBuilder: (comic) { return [ MenuEntry( @@ -159,6 +173,12 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> { Map? folders; + void showFolders() { + context + .findAncestorStateOfType<_FavoritesPageState>()! + .showFolderSelector(); + } + void loadPage() async { var res = await widget.data.loadFolders!(); _loading = false; @@ -186,13 +206,14 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> { ? IconButton( icon: const Icon(Icons.menu), color: context.colorScheme.primary, - onPressed: context - .findAncestorStateOfType<_FavoritesPageState>()! - .showFolderSelector, + onPressed: showFolders, ) : null, ), - title: Text(widget.data.title), + title: GestureDetector( + onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null, + child: Text(widget.data.title), + ), ); var appBar = Appbar( @@ -202,13 +223,14 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> { ? IconButton( icon: const Icon(Icons.menu), color: context.colorScheme.primary, - onPressed: context - .findAncestorStateOfType<_FavoritesPageState>()! - .showFolderSelector, + onPressed: showFolders, ) : null, ), - title: Text(widget.data.title), + title: GestureDetector( + onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null, + child: Text(widget.data.title), + ), ); if (_loading) { diff --git a/lib/pages/local_comics_page.dart b/lib/pages/local_comics_page.dart index 88008ea..c62e12c 100644 --- a/lib/pages/local_comics_page.dart +++ b/lib/pages/local_comics_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:venera/components/components.dart'; -import 'package:venera/foundation/app.dart'; import 'package:venera/foundation/local.dart'; import 'package:venera/pages/downloading_page.dart'; import 'package:venera/utils/translations.dart'; @@ -58,6 +57,17 @@ class _LocalComicsPageState extends State { onTap: (c) { (c as LocalComic).read(); }, + menuBuilder: (c) { + return [ + MenuEntry( + icon: Icons.delete, + text: "Delete".tl, + onClick: () { + LocalManager().deleteComic(c as LocalComic); + } + ), + ]; + }, ), ], ),