From b44998663ac3c6554d34458f1304ffe0dd66f654 Mon Sep 17 00:00:00 2001 From: nyne Date: Tue, 8 Oct 2024 08:30:08 +0800 Subject: [PATCH] local comic reading --- lib/foundation/local.dart | 55 +++++++++++++++++++++++----- lib/pages/comic_page.dart | 2 +- lib/pages/reader/images.dart | 69 ++++++++++++++++++++++++------------ lib/pages/reader/reader.dart | 10 ++++-- 4 files changed, 101 insertions(+), 35 deletions(-) diff --git a/lib/foundation/local.dart b/lib/foundation/local.dart index 1b4592e..90de45e 100644 --- a/lib/foundation/local.dart +++ b/lib/foundation/local.dart @@ -6,10 +6,11 @@ import 'package:path_provider/path_provider.dart'; import 'package:sqlite3/sqlite3.dart'; import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/comic_type.dart'; +import 'package:venera/utils/io.dart'; import 'app.dart'; -class LocalComic implements Comic{ +class LocalComic implements Comic { @override final String id; @@ -117,12 +118,12 @@ class LocalManager with ChangeNotifier { PRIMARY KEY (id, comic_type) ); '''); - if(File('${App.dataPath}/local_path').existsSync()){ + if (File('${App.dataPath}/local_path').existsSync()) { path = File('${App.dataPath}/local_path').readAsStringSync(); } else { - if(App.isAndroid) { + if (App.isAndroid) { var external = await getExternalStorageDirectories(); - if(external != null && external.isNotEmpty){ + if (external != null && external.isNotEmpty) { path = '${external.first.path}/local'; } else { path = '${App.dataPath}/local'; @@ -131,18 +132,18 @@ class LocalManager with ChangeNotifier { path = '${App.dataPath}/local'; } } - if(!Directory(path).existsSync()) { + if (!Directory(path).existsSync()) { await Directory(path).create(); } } String findValidId(ComicType type) { - final res = _db.select(''' + final res = _db.select( + ''' SELECT id FROM comics WHERE comic_type = ? ORDER BY CAST(id AS INTEGER) DESC LIMIT 1; - ''' - [type.value], + '''[type.value], ); if (res.isEmpty) { return '1'; @@ -229,4 +230,40 @@ class LocalManager with ChangeNotifier { } return LocalComic.fromRow(res.first); } -} \ No newline at end of file + + Future> getImages(String id, ComicType type, int ep) async { + var comic = find(id, type) ?? (throw "Comic Not Found"); + var directory = Directory(FilePath.join(path, comic.directory)); + if (comic.chapters != null) { + var cid = comic.chapters!.keys.elementAt(ep - 1); + directory = Directory(FilePath.join(directory.path, cid)); + } + var files = []; + await for (var entity in directory.list()) { + if (entity is File) { + if (entity.absolute.path.replaceFirst(path, '').substring(1) == + comic.cover) { + continue; + } + files.add(entity); + } + } + files.sort((a, b) { + var ai = int.tryParse(a.name.split('.').first); + var bi = int.tryParse(b.name.split('.').first); + if(ai != null && bi != null) { + return ai.compareTo(bi); + } + return a.name.compareTo(b.name); + }); + return files.map((e) => "file://${e.path}").toList(); + } + + Future isDownloaded(String id, ComicType type, int ep) async { + var comic = find(id, type); + if(comic == null) return false; + if(comic.chapters == null) return true; + var eid = comic.chapters!.keys.elementAt(ep); + return Directory(FilePath.join(path, comic.directory, eid)).exists(); + } +} diff --git a/lib/pages/comic_page.dart b/lib/pages/comic_page.dart index a994d60..2af3c64 100644 --- a/lib/pages/comic_page.dart +++ b/lib/pages/comic_page.dart @@ -462,7 +462,7 @@ abstract mixin class _ComicPageActions { void read([int? ep, int? page]) { App.rootContext.to( () => Reader( - source: comicSource, + type: comic.comicType, cid: comic.id, name: comic.title, chapters: comic.chapters, diff --git a/lib/pages/reader/images.dart b/lib/pages/reader/images.dart index 0951fb0..3cf602c 100644 --- a/lib/pages/reader/images.dart +++ b/lib/pages/reader/images.dart @@ -21,23 +21,43 @@ class _ReaderImagesState extends State<_ReaderImages> { void load() async { if (inProgress) return; inProgress = true; - var res = await context.reader.widget.source.loadComicPages!( - context.reader.widget.cid, - context.reader.widget.chapters?.keys - .elementAt(context.reader.chapter - 1), - ); - if (res.error) { - setState(() { - error = res.errorMessage; - context.reader.isLoading = false; - inProgress = false; - }); + if (context.reader.type == ComicType.local || + (await LocalManager().isDownloaded( + context.reader.cid, context.reader.type, context.reader.chapter))) { + try { + var images = await LocalManager().getImages( + context.reader.cid, context.reader.type, context.reader.chapter); + setState(() { + context.reader.images = images; + context.reader.isLoading = false; + inProgress = false; + }); + } catch (e) { + setState(() { + error = e.toString(); + context.reader.isLoading = false; + inProgress = false; + }); + } } else { - setState(() { - context.reader.images = res.data; - context.reader.isLoading = false; - inProgress = false; - }); + var res = await context.reader.type.comicSource!.loadComicPages!( + context.reader.widget.cid, + context.reader.widget.chapters?.keys + .elementAt(context.reader.chapter - 1), + ); + if (res.error) { + setState(() { + error = res.errorMessage; + context.reader.isLoading = false; + inProgress = false; + }); + } else { + setState(() { + context.reader.images = res.data; + context.reader.isLoading = false; + inProgress = false; + }); + } } context.readerScaffold.update(); } @@ -196,12 +216,17 @@ class _GalleryModeState extends State<_GalleryMode> } ImageProvider _createImageProvider(int page, BuildContext context) { - return ReaderImageProvider( - context.reader.images![page - 1], - context.reader.widget.source.key, - context.reader.cid, - context.reader.eid, - ); + var imageKey = context.reader.images![page-1]; + if(imageKey.startsWith('file://')) { + return FileImage(File(imageKey.replaceFirst("file://", ''))); + } else { + return ReaderImageProvider( + imageKey, + context.reader.type.comicSource!.key, + context.reader.cid, + context.reader.eid, + ); + } } void _precacheImage(int page, BuildContext context) { diff --git a/lib/pages/reader/reader.dart b/lib/pages/reader/reader.dart index 38f303e..956879d 100644 --- a/lib/pages/reader/reader.dart +++ b/lib/pages/reader/reader.dart @@ -10,9 +10,11 @@ import 'package:photo_view/photo_view_gallery.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/history.dart'; import 'package:venera/foundation/image_provider/reader_image.dart'; +import 'package:venera/foundation/local.dart'; +import 'package:venera/utils/io.dart'; import 'package:venera/utils/translations.dart'; import 'package:window_manager/window_manager.dart'; @@ -32,7 +34,7 @@ extension _ReaderContext on BuildContext { class Reader extends StatefulWidget { const Reader({ super.key, - required this.source, + required this.type, required this.cid, required this.name, required this.chapters, @@ -41,7 +43,7 @@ class Reader extends StatefulWidget { this.initialChapter, }); - final ComicSource source; + final ComicType type; final String cid; @@ -72,6 +74,8 @@ class _ReaderState extends State with _ReaderLocation, _ReaderWindow { @override int get maxPage => images?.length ?? 1; + ComicType get type => widget.type; + String get cid => widget.cid; String get eid => widget.chapters?.keys.elementAt(chapter - 1) ?? '0';