fix deleting local comic, favorites

This commit is contained in:
nyne
2024-10-27 16:03:46 +08:00
parent 35fb5ec752
commit fa39bdf3eb
9 changed files with 160 additions and 36 deletions

View File

@@ -50,7 +50,10 @@ class ComicTile extends StatelessWidget {
MenuEntry( MenuEntry(
icon: Icons.chrome_reader_mode_outlined, icon: Icons.chrome_reader_mode_outlined,
text: 'Details'.tl, text: 'Details'.tl,
onClick: _onTap, onClick: () {
App.mainNavigatorKey?.currentContext
?.to(() => ComicPage(id: comic.id, sourceKey: comic.sourceKey));
},
), ),
MenuEntry( MenuEntry(
icon: Icons.copy, icon: Icons.copy,

View File

@@ -180,7 +180,7 @@ class _SidebarBodyState extends State<SidebarBody> {
width: 8, width: 8,
), ),
Tooltip( Tooltip(
message: "返回", message: "Back".tl,
child: IconButton( child: IconButton(
iconSize: 25, iconSize: 25,
icon: const Icon(Icons.arrow_back), icon: const Icon(Icons.arrow_back),

View File

@@ -3,6 +3,7 @@ import 'package:venera/foundation/appdata.dart';
import 'dart:io'; import 'dart:io';
import 'app.dart'; import 'app.dart';
import 'comic_source/comic_source.dart';
import 'comic_type.dart'; import 'comic_type.dart';
String _getCurTime() { String _getCurTime() {
@@ -12,11 +13,13 @@ String _getCurTime() {
.substring(0, 19); .substring(0, 19);
} }
class FavoriteItem { class FavoriteItem implements Comic {
String name; String name;
String author; String author;
ComicType type; ComicType type;
@override
List<String> tags; List<String> tags;
@override
String id; String id;
String coverPath; String coverPath;
String time = _getCurTime(); String time = _getCurTime();
@@ -57,6 +60,38 @@ class FavoriteItem {
} }
return s; 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<String, dynamic> toJson() {
throw UnimplementedError();
}
} }
class FavoriteItemWithFolderInfo { class FavoriteItemWithFolderInfo {

View File

@@ -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.LocalFavoriteImageProvider> {
/// Image provider for normal image.
const LocalFavoriteImageProvider(this.url, this.id, this.intKey);
final String url;
final String id;
final int intKey;
@override
Future<Uint8List> load(StreamController<ImageChunkEvent> 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<LocalFavoriteImageProvider> obtainKey(ImageConfiguration configuration) {
return SynchronousFuture(this);
}
@override
String get key => id + intKey.toString();
}

View File

@@ -26,7 +26,7 @@ class LocalComic with HistoryMixin implements Comic {
@override @override
final List<String> tags; final List<String> tags;
/// name of the directory, which is in `LocalManager.path` /// The name of the directory where the comic is stored
final String directory; final String directory;
/// key: chapter id, value: chapter title /// key: chapter id, value: chapter title
@@ -143,6 +143,7 @@ class LocalManager with ChangeNotifier {
late Database _db; late Database _db;
/// path to the directory where all the comics are stored
late String path; late String path;
// return error message if failed // return error message if failed
@@ -413,4 +414,11 @@ class LocalManager with ChangeNotifier {
saveCurrentDownloadingTasks(); saveCurrentDownloadingTasks();
downloadingTasks.first.resume(); 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();
}
} }

View File

@@ -64,6 +64,7 @@ class _CommentsPageState extends State<CommentsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false,
appBar: Appbar( appBar: Appbar(
title: Text("Comments".tl), title: Text("Comments".tl),
), ),

View File

@@ -42,7 +42,12 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
) )
: const SizedBox(), : const SizedBox(),
), ),
title: Text(favPage.folder ?? "Unselected".tl), title: GestureDetector(
onTap: context.width < _kTwoPanelChangeWidth
? favPage.showFolderSelector
: null,
child: Text(favPage.folder ?? "Unselected".tl),
),
actions: [ actions: [
MenuButton( MenuButton(
entries: [ entries: [
@@ -110,20 +115,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
], ],
), ),
SliverGridComics( SliverGridComics(
comics: comics.map((e) { comics: comics,
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(),
menuBuilder: (c) { menuBuilder: (c) {
return [ return [
MenuEntry( MenuEntry(
@@ -138,7 +130,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
LocalFavoritesManager().deleteComicWithId( LocalFavoritesManager().deleteComicWithId(
widget.folder, widget.folder,
c.id, c.id,
ComicType(c.sourceKey.hashCode), (c as FavoriteItem).type,
); );
updateComics(); updateComics();
}, },

View File

@@ -83,6 +83,12 @@ class _NormalFavoritePage extends StatefulWidget {
class _NormalFavoritePageState extends State<_NormalFavoritePage> { class _NormalFavoritePageState extends State<_NormalFavoritePage> {
final comicListKey = GlobalKey<ComicListState>(); final comicListKey = GlobalKey<ComicListState>();
void showFolders() {
context
.findAncestorStateOfType<_FavoritesPageState>()!
.showFolderSelector();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ComicList( return ComicList(
@@ -94,13 +100,14 @@ class _NormalFavoritePageState extends State<_NormalFavoritePage> {
? IconButton( ? IconButton(
icon: const Icon(Icons.menu), icon: const Icon(Icons.menu),
color: context.colorScheme.primary, color: context.colorScheme.primary,
onPressed: context onPressed: showFolders,
.findAncestorStateOfType<_FavoritesPageState>()!
.showFolderSelector,
) )
: null, : null,
), ),
title: Text(widget.data.title), title: GestureDetector(
onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null,
child: Text(widget.data.title),
),
), ),
errorLeading: Appbar( errorLeading: Appbar(
leading: Tooltip( leading: Tooltip(
@@ -115,10 +122,17 @@ class _NormalFavoritePageState extends State<_NormalFavoritePage> {
) )
: null, : 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), loadPage: widget.data.loadComic == null
loadNext: widget.data.loadNext == null ? null : (next) => widget.data.loadNext!(next), ? null
: (i) => widget.data.loadComic!(i),
loadNext: widget.data.loadNext == null
? null
: (next) => widget.data.loadNext!(next),
menuBuilder: (comic) { menuBuilder: (comic) {
return [ return [
MenuEntry( MenuEntry(
@@ -159,6 +173,12 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> {
Map<String, String>? folders; Map<String, String>? folders;
void showFolders() {
context
.findAncestorStateOfType<_FavoritesPageState>()!
.showFolderSelector();
}
void loadPage() async { void loadPage() async {
var res = await widget.data.loadFolders!(); var res = await widget.data.loadFolders!();
_loading = false; _loading = false;
@@ -186,13 +206,14 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> {
? IconButton( ? IconButton(
icon: const Icon(Icons.menu), icon: const Icon(Icons.menu),
color: context.colorScheme.primary, color: context.colorScheme.primary,
onPressed: context onPressed: showFolders,
.findAncestorStateOfType<_FavoritesPageState>()!
.showFolderSelector,
) )
: null, : null,
), ),
title: Text(widget.data.title), title: GestureDetector(
onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null,
child: Text(widget.data.title),
),
); );
var appBar = Appbar( var appBar = Appbar(
@@ -202,13 +223,14 @@ class _MultiFolderFavoritesPageState extends State<_MultiFolderFavoritesPage> {
? IconButton( ? IconButton(
icon: const Icon(Icons.menu), icon: const Icon(Icons.menu),
color: context.colorScheme.primary, color: context.colorScheme.primary,
onPressed: context onPressed: showFolders,
.findAncestorStateOfType<_FavoritesPageState>()!
.showFolderSelector,
) )
: null, : null,
), ),
title: Text(widget.data.title), title: GestureDetector(
onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null,
child: Text(widget.data.title),
),
); );
if (_loading) { if (_loading) {

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:venera/components/components.dart'; import 'package:venera/components/components.dart';
import 'package:venera/foundation/app.dart';
import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/local.dart';
import 'package:venera/pages/downloading_page.dart'; import 'package:venera/pages/downloading_page.dart';
import 'package:venera/utils/translations.dart'; import 'package:venera/utils/translations.dart';
@@ -58,6 +57,17 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
onTap: (c) { onTap: (c) {
(c as LocalComic).read(); (c as LocalComic).read();
}, },
menuBuilder: (c) {
return [
MenuEntry(
icon: Icons.delete,
text: "Delete".tl,
onClick: () {
LocalManager().deleteComic(c as LocalComic);
}
),
];
},
), ),
], ],
), ),