diff --git a/lib/modules/browse/sources/widgets/source_list_tile.dart b/lib/modules/browse/sources/widgets/source_list_tile.dart index 28a4bf62..76985e7d 100644 --- a/lib/modules/browse/sources/widgets/source_list_tile.dart +++ b/lib/modules/browse/sources/widgets/source_list_tile.dart @@ -1,21 +1,25 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:isar/isar.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/source.dart'; +import 'package:mangayomi/providers/l10n_providers.dart'; +import 'package:mangayomi/services/supports_latest.dart'; import 'package:mangayomi/sources/source_test.dart'; import 'package:mangayomi/utils/colors.dart'; import 'package:mangayomi/utils/language.dart'; import 'package:cached_network_image/cached_network_image.dart'; -class SourceListTile extends StatelessWidget { +class SourceListTile extends ConsumerWidget { final bool isManga; final Source source; const SourceListTile( {super.key, required this.source, required this.isManga}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final supportsLatest = ref.watch(supportsLatestProvider(source: source)); return ListTile( onTap: () { if (useTestSourceCode) { @@ -34,7 +38,7 @@ class SourceListTile extends StatelessWidget { } }); - context.push('/mangaHome', extra: source); + context.push('/mangaHome', extra: (source, false)); }, leading: Container( height: 37, @@ -96,15 +100,32 @@ class SourceListTile extends StatelessWidget { ], ), title: Text(source.name!), - trailing: IconButton( - onPressed: () { - isar.writeTxnSync(() => - isar.sources.putSync(source..isPinned = !source.isPinned!)); - }, - icon: Icon( - Icons.push_pin_outlined, - color: source.isPinned! ? primaryColor(context) : null, - )), + trailing: SizedBox( + width: 150, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (supportsLatest) + TextButton( + style: const ButtonStyle( + padding: MaterialStatePropertyAll(EdgeInsets.all(10))), + onPressed: () => + context.push('/mangaHome', extra: (source, true)), + child: Text(context.l10n.latest)), + const SizedBox(width: 10), + IconButton( + padding: const EdgeInsets.all(0), + onPressed: () { + isar.writeTxnSync(() => isar.sources + .putSync(source..isPinned = !source.isPinned!)); + }, + icon: Icon( + Icons.push_pin_outlined, + color: source.isPinned! ? primaryColor(context) : null, + )), + ], + ), + ), ); } } diff --git a/lib/modules/library/library_screen.dart b/lib/modules/library/library_screen.dart index 39e65081..a082347a 100644 --- a/lib/modules/library/library_screen.dart +++ b/lib/modules/library/library_screen.dart @@ -1130,34 +1130,36 @@ class _LibraryScreenState extends ConsumerState for (var manga in mangasList) { if (manga.isLocalArchive ?? false) { for (var chapter in manga.chapters) { - final storageProvider = - StorageProvider(); - final mangaDir = await storageProvider - .getMangaMainDirectory(chapter); - final path = await storageProvider - .getMangaChapterDirectory( - chapter, - ); - try { - if (await File( - "${mangaDir!.path}${chapter.name}.cbz") - .exists()) { - File("${mangaDir.path}${chapter.name}.cbz") - .deleteSync(); - } - path!.deleteSync(recursive: true); + final storageProvider = + StorageProvider(); + final mangaDir = await storageProvider + .getMangaMainDirectory(chapter); + final path = await storageProvider + .getMangaChapterDirectory( + chapter, + ); + + try { + if (await File( + "${mangaDir!.path}${chapter.name}.cbz") + .exists()) { + File("${mangaDir.path}${chapter.name}.cbz") + .deleteSync(); + } + path!.deleteSync(recursive: true); + } catch (_) {} + isar.writeTxnSync(() { + final download = isar.downloads + .filter() + .chapterIdEqualTo(chapter.id!) + .findAllSync(); + if (download.isNotEmpty) { + isar.downloads.deleteSync( + download.first.id!); + } + }); } catch (_) {} - isar.writeTxnSync(() { - final download = isar.downloads - .filter() - .chapterIdEqualTo(chapter.id!) - .findAllSync(); - if (download.isNotEmpty) { - isar.downloads - .deleteSync(download.first.id!); - } - }); } } } diff --git a/lib/modules/library/providers/library_state_provider.dart b/lib/modules/library/providers/library_state_provider.dart index a23ee1f2..d9fe83ac 100644 --- a/lib/modules/library/providers/library_state_provider.dart +++ b/lib/modules/library/providers/library_state_provider.dart @@ -3,6 +3,7 @@ import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; +import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'library_state_provider.g.dart'; @@ -620,17 +621,21 @@ class MangasSetIsReadState extends _$MangasSetIsReadState { @override void build({required List mangaIds}) {} - set() { + void set() { for (var mangaid in mangaIds) { final manga = isar.mangas.getSync(mangaid)!; final chapters = manga.chapters; - isar.writeTxnSync(() { - for (var chapter in chapters) { - chapter.isRead = true; - isar.chapters.putSync(chapter..manga.value = manga); - chapter.manga.saveSync(); - } - }); + if (chapters.isNotEmpty) { + chapters.last.updateTrackChapterRead(ref); + isar.writeTxnSync(() { + for (var chapter in chapters) { + chapter.isRead = true; + chapter.lastPageRead = "1"; + isar.chapters.putSync(chapter..manga.value = manga); + chapter.manga.saveSync(); + } + }); + } } ref.read(isLongPressedMangaStateProvider.notifier).update(false); @@ -643,7 +648,7 @@ class MangasSetUnReadState extends _$MangasSetUnReadState { @override void build({required List mangaIds}) {} - set() { + void set() { for (var mangaid in mangaIds) { final manga = isar.mangas.getSync(mangaid)!; final chapters = manga.chapters; diff --git a/lib/modules/manga/detail/manga_detail_view.dart b/lib/modules/manga/detail/manga_detail_view.dart index 06ef1a4d..4d3ee2bb 100644 --- a/lib/modules/manga/detail/manga_detail_view.dart +++ b/lib/modules/manga/detail/manga_detail_view.dart @@ -20,6 +20,7 @@ import 'package:mangayomi/modules/library/providers/local_archive.dart'; import 'package:mangayomi/modules/manga/detail/providers/track_state_providers.dart'; import 'package:mangayomi/modules/manga/detail/widgets/tracker_search_widget.dart'; import 'package:mangayomi/modules/manga/detail/widgets/tracker_widget.dart'; +import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart'; import 'package:mangayomi/modules/more/settings/appearance/providers/pure_black_dark_mode_state_provider.dart'; import 'package:mangayomi/modules/more/settings/track/widgets/track_listile.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; @@ -624,6 +625,9 @@ class _MangaDetailViewState extends ConsumerState isar.chapters.putSync( chapter..manga.value = widget.manga); chapter.manga.saveSync(); + if (chapter.isRead!) { + chapter.updateTrackChapterRead(ref); + } } }); ref @@ -655,14 +659,18 @@ class _MangaDetailViewState extends ConsumerState ), onPressed: () { int index = chapters.indexOf(chap.first); + chapters[index + 1].updateTrackChapterRead(ref); isar.writeTxnSync(() { for (var i = index + 1; i < chapters.length; i++) { - chapters[i].isRead = true; - isar.chapters.putSync(chapters[i] - ..manga.value = widget.manga); - chapters[i].manga.saveSync(); + if (!chapters[i].isRead!) { + chapters[i].isRead = true; + chapters[i].lastPageRead = "1"; + isar.chapters.putSync(chapters[i] + ..manga.value = widget.manga); + chapters[i].manga.saveSync(); + } } ref .read(isLongPressedStateProvider.notifier) diff --git a/lib/modules/manga/home/manga_home_screen.dart b/lib/modules/manga/home/manga_home_screen.dart index 9d9611f6..8b2459d4 100644 --- a/lib/modules/manga/home/manga_home_screen.dart +++ b/lib/modules/manga/home/manga_home_screen.dart @@ -23,11 +23,13 @@ import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart'; class MangaHomeScreen extends ConsumerStatefulWidget { final Source source; final bool isSearch; + final bool isLatest; final String query; const MangaHomeScreen( {required this.source, this.query = "", this.isSearch = false, + this.isLatest = false, super.key}); @override @@ -48,7 +50,11 @@ class _MangaHomeScreenState extends ConsumerState { final ScrollController _scrollController = ScrollController(); int _fullDataLength = 50; int _page = 1; - late int _selectedIndex = widget.isSearch ? 2 : 0; + late int _selectedIndex = widget.isLatest + ? 1 + : widget.isSearch + ? 2 + : 0; List filters = []; final List _mangaList = []; List _types(BuildContext context) { diff --git a/lib/modules/manga/reader/providers/reader_controller_provider.dart b/lib/modules/manga/reader/providers/reader_controller_provider.dart index 9e89e41c..31159e89 100644 --- a/lib/modules/manga/reader/providers/reader_controller_provider.dart +++ b/lib/modules/manga/reader/providers/reader_controller_provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/chapter.dart'; @@ -321,7 +322,7 @@ class ReaderController extends _$ReaderController { } chapterPageIndexs.add(ChapterPageIndex() ..chapterId = chapter.id - ..index = newIndex); + ..index = isRead ? 0 : newIndex); final chap = chapter; isar.writeTxnSync(() { isar.settings.putSync( @@ -350,7 +351,8 @@ class ReaderController extends _$ReaderController { } extension ChapterExtensions on Chapter { - void updateTrackChapterRead(AutoDisposeNotifierProviderRef ref) { + void updateTrackChapterRead(dynamic ref) { + if (!(ref is WidgetRef || ref is AutoDisposeNotifierProviderRef)) return; final updateProgressAfterReading = ref.watch(updateProgressAfterReadingStateProvider); if (!updateProgressAfterReading) return; diff --git a/lib/router/router.dart b/lib/router/router.dart index 1d3a6e8d..fc25d885 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -143,17 +143,19 @@ class RouterNotifier extends ChangeNotifier { path: "/mangaHome", name: "mangaHome", builder: (context, state) { - final source = state.extra as Source?; + final source = state.extra as (Source?, bool); return MangaHomeScreen( - source: source!, + source: source.$1!, + isLatest: source.$2, ); }, pageBuilder: (context, state) { - final source = state.extra as Source?; + final source = state.extra as (Source?, bool); return transitionPage( key: state.pageKey, child: MangaHomeScreen( - source: source!, + source: source.$1!, + isLatest: source.$2, ), ); }),