Skip filtered out chapters in reader #70

This commit is contained in:
kodjomoustapha 2023-12-18 11:16:30 +01:00
parent 782995f5a0
commit c927475720
11 changed files with 379 additions and 91 deletions

View file

@ -749,9 +749,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
List<Widget> _desktopBottomButtonBar(
BuildContext context, bool isFullScreen) {
bool hasPrevEpisode = _streamController.getEpisodeIndex() + 1 !=
_streamController.getEpisodesLength();
bool hasNextEpisode = _streamController.getEpisodeIndex() != 0;
bool hasPrevEpisode = _streamController.getEpisodeIndex().$1 + 1 !=
_streamController
.getEpisodesLength(_streamController.getEpisodeIndex().$2);
bool hasNextEpisode = _streamController.getEpisodeIndex().$1 != 0;
return [
Flexible(
child: Column(
@ -1010,9 +1011,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
}
List<Widget> _mobilePrimaryButtonBar() {
bool hasPrevEpisode = _streamController.getEpisodeIndex() + 1 !=
_streamController.getEpisodesLength();
bool hasNextEpisode = _streamController.getEpisodeIndex() != 0;
bool hasPrevEpisode = _streamController.getEpisodeIndex().$1 + 1 !=
_streamController
.getEpisodesLength(_streamController.getEpisodeIndex().$2);
bool hasNextEpisode = _streamController.getEpisodeIndex().$1 != 0;
return [
const Spacer(flex: 3),
IconButton(

View file

@ -1,6 +1,7 @@
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/download.dart';
import 'package:mangayomi/models/history.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/settings.dart';
@ -19,57 +20,84 @@ class AnimeStreamController {
return isar.settings.getSync(227)!;
}
int getEpisodeIndex() {
final chapters = getAnime().chapters.toList().reversed.toList();
(int, bool) getEpisodeIndex() {
final episodes = _filterAndSortEpisodes();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == episode.id) {
for (var i = 0; i < episodes.length; i++) {
if (episodes[i].id == episode.id) {
index = i;
}
}
return index!;
if (index == null) {
final chapters = getAnime().chapters.toList().reversed.toList();
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == episode.id) {
index = i;
}
}
return (index!, false);
}
return (index, true);
}
int getPrevEpisodeIndex() {
final episodes = getAnime().chapters.toList().reversed.toList();
(int, bool) getPrevEpisodeIndex() {
final episodes = _filterAndSortEpisodes();
int? index;
for (var i = 0; i < episodes.length; i++) {
if (episodes[i].id == episode.id) {
index = i + 1;
}
}
return index!;
if (index == null) {
final chapters = getAnime().chapters.toList().reversed.toList();
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == episode.id) {
index = i + 1;
}
}
return (index!, false);
}
return (index, true);
}
int getNextEpisodeIndex() {
final episodes = getAnime().chapters.toList().reversed.toList();
(int, bool) getNextEpisodeIndex() {
final episodes = _filterAndSortEpisodes();
int? index;
for (var i = 0; i < episodes.length; i++) {
if (episodes[i].id == episode.id) {
index = i - 1;
}
}
return index!;
if (index == null) {
final chapters = getAnime().chapters.toList().reversed.toList();
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == episode.id) {
index = i - 1;
}
}
return (index!, false);
}
return (index, true);
}
Chapter getPrevEpisode() {
return getAnime()
.chapters
.toList()
.reversed
.toList()[getPrevEpisodeIndex()];
final prevEpIdx = getPrevEpisodeIndex();
return prevEpIdx.$2
? _filterAndSortEpisodes()[prevEpIdx.$1]
: getAnime().chapters.toList().reversed.toList()[prevEpIdx.$1];
}
Chapter getNextEpisode() {
return getAnime()
.chapters
.toList()
.reversed
.toList()[getNextEpisodeIndex()];
final nextEpIdx = getNextEpisodeIndex();
return nextEpIdx.$2
? _filterAndSortEpisodes()[nextEpIdx.$1]
: getAnime().chapters.toList().reversed.toList()[nextEpIdx.$1];
}
int getEpisodesLength() {
return getAnime().chapters.length;
int getEpisodesLength(bool isInFilterList) {
return isInFilterList
? _filterAndSortEpisodes().length
: getAnime().chapters.length;
}
Duration geTCurrentPosition() {
@ -128,4 +156,107 @@ class AnimeStreamController {
}
}
}
List<String>? _getFilterScanlator() {
final scanlators = isar.settings.getSync(227)!.filterScanlatorList ?? [];
final filter = scanlators
.where((element) => element.mangaId == getAnime().id)
.toList();
return filter.isEmpty ? null : filter.first.scanlators;
}
List<Chapter> _filterAndSortEpisodes() {
final data = _filterAndSortEpisodes();
final filterUnread = isar.settings
.getSync(227)!
.chapterFilterUnreadList!
.where((element) => element.mangaId == getAnime().id)
.toList()
.first
.type!;
final filterBookmarked = isar.settings
.getSync(227)!
.chapterFilterBookmarkedList!
.where((element) => element.mangaId == getAnime().id)
.toList()
.first
.type!;
final filterDownloaded = isar.settings
.getSync(227)!
.chapterFilterDownloadedList!
.where((element) => element.mangaId == getAnime().id)
.toList()
.first
.type!;
final sortChapter = isar.settings
.getSync(227)!
.sortChapterList!
.where((element) => element.mangaId == getAnime().id)
.toList()
.first
.index;
final filterScanlator = _getFilterScanlator() ?? [];
List<Chapter>? chapterList;
chapterList = data
.where((element) => filterUnread == 1
? element.isRead == false
: filterUnread == 2
? element.isRead == true
: true)
.where((element) => filterBookmarked == 1
? element.isBookmarked == true
: filterBookmarked == 2
? element.isBookmarked == false
: true)
.where((element) {
final modelChapDownload = isar.downloads
.filter()
.idIsNotNull()
.chapterIdEqualTo(element.id)
.findAllSync();
return filterDownloaded == 1
? modelChapDownload.isNotEmpty &&
modelChapDownload.first.isDownload == true
: filterDownloaded == 2
? !(modelChapDownload.isNotEmpty &&
modelChapDownload.first.isDownload == true)
: true;
})
.where((element) => !filterScanlator.contains(element.scanlator))
.toList();
List<Chapter> chapters =
sortChapter == 1 ? chapterList.reversed.toList() : chapterList;
if (sortChapter == 0) {
chapters.sort(
(a, b) {
return (a.scanlator == null ||
b.scanlator == null ||
a.dateUpload == null ||
b.dateUpload == null)
? 0
: a.scanlator!.compareTo(b.scanlator!) |
a.dateUpload!.compareTo(b.dateUpload!);
},
);
} else if (sortChapter == 2) {
chapters.sort(
(a, b) {
return (a.dateUpload == null || b.dateUpload == null)
? 0
: int.parse(a.dateUpload!).compareTo(int.parse(b.dateUpload!));
},
);
} else if (sortChapter == 3) {
chapters.sort(
(a, b) {
return (a.name == null || b.name == null)
? 0
: a.name!.compareTo(b.name!);
},
);
}
return chapterList;
}
}

View file

@ -10,22 +10,13 @@ import 'package:mangayomi/modules/more/settings/downloads/providers/downloads_st
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/services/get_video_list.dart';
import 'package:mangayomi/services/get_chapter_pages.dart';
import 'package:mangayomi/utils/extensions.dart';
import 'package:mangayomi/utils/headers.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
import 'package:path_provider/path_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'download_provider.g.dart';
bool _canBeDownloaded(String url) {
List<String> extensions = ['mp4', 'mov', 'avi', 'mkv'];
for (String extension in extensions) {
if (url.toLowerCase().endsWith(extension)) {
return true;
}
}
return false;
}
@riverpod
Future<List<String>> downloadChapter(
DownloadChapterRef ref, {
@ -87,7 +78,7 @@ Future<List<String>> downloadChapter(
).future)
.then((value) {
final videosUrls = value.$1
.where((element) => _canBeDownloaded(element.originalUrl))
.where((element) => element.originalUrl.isMediaVideo())
.toList();
if (videosUrls.isNotEmpty) {
pageUrls = [videosUrls.first.url];

View file

@ -6,7 +6,7 @@ part of 'download_provider.dart';
// RiverpodGenerator
// **************************************************************************
String _$downloadChapterHash() => r'41a09ffc4ef02f061eb0a5d0bfa6410d12dc6c4a';
String _$downloadChapterHash() => r'5d6f104706b7f29989ef52b67eccfb4142584777';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/download.dart';
import 'package:mangayomi/models/history.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/settings.dart';
@ -196,57 +197,84 @@ class ReaderController {
return isar.chapters.getSync(chapter.id!)!.isBookmarked!;
}
int getPrevChapterIndex() {
final chapters = getManga().chapters.toList().reversed.toList();
(int, bool) getPrevChapterIndex() {
final chapters = _filterAndSortChapters();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i + 1;
}
}
return index!;
if (index == null) {
final chapters = getManga().chapters.toList().reversed.toList();
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i + 1;
}
}
return (index!, false);
}
return (index, true);
}
int getNextChapterIndex() {
final chapters = getManga().chapters.toList().reversed.toList();
(int, bool) getNextChapterIndex() {
final chapters = _filterAndSortChapters();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i - 1;
}
}
return index!;
if (index == null) {
final chapters = getManga().chapters.toList().reversed.toList();
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i - 1;
}
}
return (index!, false);
}
return (index, true);
}
int getChapterIndex() {
final chapters = getManga().chapters.toList().reversed.toList();
(int, bool) getChapterIndex() {
final chapters = _filterAndSortChapters();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i;
}
}
return index!;
if (index == null) {
final chapters = getManga().chapters.toList().reversed.toList();
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i;
}
}
return (index!, false);
}
return (index, true);
}
Chapter getPrevChapter() {
return getManga()
.chapters
.toList()
.reversed
.toList()[getPrevChapterIndex()];
final prevChapIdx = getPrevChapterIndex();
return prevChapIdx.$2
? _filterAndSortChapters()[prevChapIdx.$1]
: getManga().chapters.toList().reversed.toList()[prevChapIdx.$1];
}
Chapter getNextChapter() {
return getManga()
.chapters
.toList()
.reversed
.toList()[getNextChapterIndex()];
final nextChapIdx = getNextChapterIndex();
return nextChapIdx.$2
? _filterAndSortChapters()[nextChapIdx.$1]
: getManga().chapters.toList().reversed.toList()[nextChapIdx.$1];
}
int getChaptersLength() {
return getManga().chapters.length;
int getChaptersLength(bool isInFilterList) {
return isInFilterList
? _filterAndSortChapters().length
: getManga().chapters.length;
}
int getPageIndex() {
@ -301,6 +329,109 @@ class ReaderController {
}
}
List<String>? _getFilterScanlator() {
final scanlators = isar.settings.getSync(227)!.filterScanlatorList ?? [];
final filter = scanlators
.where((element) => element.mangaId == getManga().id)
.toList();
return filter.isEmpty ? null : filter.first.scanlators;
}
List<Chapter> _filterAndSortChapters() {
final data = getManga().chapters.toList().reversed.toList();
final filterUnread = isar.settings
.getSync(227)!
.chapterFilterUnreadList!
.where((element) => element.mangaId == getManga().id)
.toList()
.first
.type!;
final filterBookmarked = isar.settings
.getSync(227)!
.chapterFilterBookmarkedList!
.where((element) => element.mangaId == getManga().id)
.toList()
.first
.type!;
final filterDownloaded = isar.settings
.getSync(227)!
.chapterFilterDownloadedList!
.where((element) => element.mangaId == getManga().id)
.toList()
.first
.type!;
final sortChapter = isar.settings
.getSync(227)!
.sortChapterList!
.where((element) => element.mangaId == getManga().id)
.toList()
.first
.index;
final filterScanlator = _getFilterScanlator() ?? [];
List<Chapter>? chapterList;
chapterList = data
.where((element) => filterUnread == 1
? element.isRead == false
: filterUnread == 2
? element.isRead == true
: true)
.where((element) => filterBookmarked == 1
? element.isBookmarked == true
: filterBookmarked == 2
? element.isBookmarked == false
: true)
.where((element) {
final modelChapDownload = isar.downloads
.filter()
.idIsNotNull()
.chapterIdEqualTo(element.id)
.findAllSync();
return filterDownloaded == 1
? modelChapDownload.isNotEmpty &&
modelChapDownload.first.isDownload == true
: filterDownloaded == 2
? !(modelChapDownload.isNotEmpty &&
modelChapDownload.first.isDownload == true)
: true;
})
.where((element) => !filterScanlator.contains(element.scanlator))
.toList();
List<Chapter> chapters =
sortChapter == 1 ? chapterList.reversed.toList() : chapterList;
if (sortChapter == 0) {
chapters.sort(
(a, b) {
return (a.scanlator == null ||
b.scanlator == null ||
a.dateUpload == null ||
b.dateUpload == null)
? 0
: a.scanlator!.compareTo(b.scanlator!) |
a.dateUpload!.compareTo(b.dateUpload!);
},
);
} else if (sortChapter == 2) {
chapters.sort(
(a, b) {
return (a.dateUpload == null || b.dateUpload == null)
? 0
: int.parse(a.dateUpload!).compareTo(int.parse(b.dateUpload!));
},
);
} else if (sortChapter == 3) {
chapters.sort(
(a, b) {
return (a.name == null || b.name == null)
? 0
: a.name!.compareTo(b.name!);
},
);
}
return chapterList;
}
String getMangaName() {
return getManga().name!;
}

View file

@ -272,9 +272,10 @@ class _MangaChapterPageGalleryState
if (event is KeyDownEvent) {
return;
}
bool hasNextChapter = _readerController.getChapterIndex() != 0;
bool hasPrevChapter = _readerController.getChapterIndex() + 1 !=
_readerController.getChaptersLength();
bool hasNextChapter = _readerController.getChapterIndex().$1 != 0;
bool hasPrevChapter = _readerController.getChapterIndex().$1 + 1 !=
_readerController
.getChaptersLength(_readerController.getChapterIndex().$2);
final action = switch (event.logicalKey) {
LogicalKeyboardKey.escape => _goBack(context),
LogicalKeyboardKey.backspace => _goBack(context),
@ -1196,28 +1197,29 @@ class _MangaChapterPageGalleryState
right: 0,
child: !_isView
? ValueListenableBuilder(
valueListenable: _autoScrollPage,
builder: (context, valueT, child) => valueT
? ValueListenableBuilder(
valueListenable: _autoScroll,
builder: (context, value, child) => IconButton(
onPressed: () {
autoPagescroll();
_autoScroll.value = !value;
},
icon: Icon(value
? Icons.pause_circle
: Icons.play_circle)),
)
: Container(),
)
valueListenable: _autoScrollPage,
builder: (context, valueT, child) => valueT
? ValueListenableBuilder(
valueListenable: _autoScroll,
builder: (context, value, child) => IconButton(
onPressed: () {
autoPagescroll();
_autoScroll.value = !value;
},
icon: Icon(value
? Icons.pause_circle
: Icons.play_circle)),
)
: Container(),
)
: Container());
}
Widget _bottomBar() {
bool hasPrevChapter = _readerController.getChapterIndex() + 1 !=
_readerController.getChaptersLength();
bool hasNextChapter = _readerController.getChapterIndex() != 0;
bool hasPrevChapter = _readerController.getChapterIndex().$1 + 1 !=
_readerController
.getChaptersLength(_readerController.getChapterIndex().$2);
bool hasNextChapter = _readerController.getChapterIndex().$1 != 0;
final readerMode = ref.watch(_currentReaderMode);
return Positioned(
bottom: 0,

View file

@ -19,7 +19,7 @@ checkForUpdate(CheckForUpdateRef ref,
BotToast.showText(text: l10n.searching_for_updates);
}
final info = await PackageInfo.fromPlatform();
print(info.data);
final updateAvailable = await _checkUpdate();
if (compareVersions(info.version, updateAvailable.$1) < 0) {
if (manualUpdate) {

View file

@ -1,3 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/modules/more/widgets/list_tile_widget.dart';
@ -26,11 +29,20 @@ class SettingsScreen extends StatelessWidget {
subtitle: l10n.appearance_subtitle,
icon: Icons.color_lens_rounded,
onTap: () => context.push('/appearance')),
// ListTileWidget(
// title: l10n.library,
// subtitle: 'Categories',
// icon: Icons.collections_bookmark_rounded,
// onTap: () {}),
ListTileWidget(
title: l10n.library,
subtitle: 'Categories',
icon: Icons.collections_bookmark_rounded,
onTap: () async {
final process = await Process.start(
"C:/DEV/flutter/mangayomi/server/TorrServer.exe",
[],
workingDirectory: "C:/DEV/flutter/mangayomi/server",
);
await process.stderr.forEach((e) {
print(utf8.decode(e));
});
}),
ListTileWidget(
title: l10n.reader,
subtitle: l10n.reader_subtitle,

View file

@ -6,7 +6,7 @@ part of 'get_video_list.dart';
// RiverpodGenerator
// **************************************************************************
String _$getVideoListHash() => r'924c2961d148f9ebb0952239c0528d5269a4526a';
String _$getVideoListHash() => r'aafdf726ba8dd830fea1f9a2784012258bf541bb';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'anilist.dart';
// RiverpodGenerator
// **************************************************************************
String _$anilistHash() => r'ee83d9fc6e85366bb7cbce876b0878207829a979';
String _$anilistHash() => r'cbb2453079f6a24012e14d9c5ca3d5003ec61360';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -35,6 +35,25 @@ extension StringExtensions on String {
startIndex = rightIndex + right.length;
return substring(leftIndex, rightIndex);
}
bool isMediaVideo() {
return [
"3gp",
"avi",
"mpg",
"mpeg",
"webm",
"ogg",
"flv",
"m4v",
"mvp",
"mp4",
"wmv",
"mkv",
"mov",
"ts"
].any((extension) => toLowerCase().endsWith(extension));
}
}
extension LetExtension<T> on T {