mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
fix deleting local comic, favorites
This commit is contained in:
@@ -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,
|
||||
|
@@ -180,7 +180,7 @@ class _SidebarBodyState extends State<SidebarBody> {
|
||||
width: 8,
|
||||
),
|
||||
Tooltip(
|
||||
message: "返回",
|
||||
message: "Back".tl,
|
||||
child: IconButton(
|
||||
iconSize: 25,
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
|
@@ -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<String> 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<String, dynamic> toJson() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
class FavoriteItemWithFolderInfo {
|
||||
|
53
lib/foundation/image_provider/local_favorite_image.dart
Normal file
53
lib/foundation/image_provider/local_favorite_image.dart
Normal 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();
|
||||
}
|
@@ -26,7 +26,7 @@ class LocalComic with HistoryMixin implements Comic {
|
||||
@override
|
||||
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;
|
||||
|
||||
/// 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();
|
||||
}
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ class _CommentsPageState extends State<CommentsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: Appbar(
|
||||
title: Text("Comments".tl),
|
||||
),
|
||||
|
@@ -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();
|
||||
},
|
||||
|
@@ -83,6 +83,12 @@ class _NormalFavoritePage extends StatefulWidget {
|
||||
class _NormalFavoritePageState extends State<_NormalFavoritePage> {
|
||||
final comicListKey = GlobalKey<ComicListState>();
|
||||
|
||||
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<String, String>? 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) {
|
||||
|
@@ -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<LocalComicsPage> {
|
||||
onTap: (c) {
|
||||
(c as LocalComic).read();
|
||||
},
|
||||
menuBuilder: (c) {
|
||||
return [
|
||||
MenuEntry(
|
||||
icon: Icons.delete,
|
||||
text: "Delete".tl,
|
||||
onClick: () {
|
||||
LocalManager().deleteComic(c as LocalComic);
|
||||
}
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
Reference in New Issue
Block a user