mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 23:22:07 +00:00
Finish migration hive to isar database & big changes
This commit is contained in:
parent
181647512e
commit
07b8f4303a
70 changed files with 7790 additions and 1192 deletions
|
|
@ -1,11 +1,9 @@
|
|||
// ignore_for_file: depend_on_referenced_packages
|
||||
import 'dart:io';
|
||||
import 'package:fast_cached_network_image/fast_cached_network_image.dart';
|
||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/models/category.dart';
|
||||
|
|
@ -13,14 +11,15 @@ import 'package:mangayomi/models/chapter.dart';
|
|||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/reader_settings.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/router/router.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/blend_level_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/flex_scheme_color_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
late Isar isar;
|
||||
void main() async {
|
||||
|
|
@ -30,15 +29,8 @@ void main() async {
|
|||
}
|
||||
|
||||
_initDB() async {
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
await Hive.initFlutter();
|
||||
await FastCachedImageConfig.init();
|
||||
} else {
|
||||
await Hive.initFlutter("Mangayomi/databases");
|
||||
await FastCachedImageConfig.init(subDir: "Mangayomi/databases");
|
||||
}
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
|
||||
isar = Isar.openSync(
|
||||
[
|
||||
MangaSchema,
|
||||
|
|
@ -48,11 +40,14 @@ _initDB() async {
|
|||
DownloadSchema,
|
||||
SourceSchema,
|
||||
PersonalReaderModeSchema,
|
||||
ReaderSettingsSchema
|
||||
ReaderSettingsSchema,
|
||||
SettingsSchema
|
||||
],
|
||||
directory: dir.path,
|
||||
);
|
||||
} else {
|
||||
String dbDir = path.join(dir.path, 'Mangayomi', 'databases');
|
||||
await Directory(dbDir).create(recursive: true);
|
||||
isar = await Isar.open([
|
||||
MangaSchema,
|
||||
ChapterSchema,
|
||||
|
|
@ -61,11 +56,25 @@ _initDB() async {
|
|||
DownloadSchema,
|
||||
SourceSchema,
|
||||
PersonalReaderModeSchema,
|
||||
ReaderSettingsSchema
|
||||
], directory: "${dir.path}/Mangayomi/databases", name: "mangayomiDb");
|
||||
ReaderSettingsSchema,
|
||||
SettingsSchema
|
||||
], directory: dbDir, name: "mangayomiDb");
|
||||
}
|
||||
if (isar.settings.filter().idEqualTo(227).isEmptySync()) {
|
||||
isar.writeTxnSync(
|
||||
() {
|
||||
isar.settings.putSync(Settings()
|
||||
..sortLibraryManga = SortLibraryManga()
|
||||
..sortChapterList = []
|
||||
..chapterFilterBookmarkedList = []
|
||||
..chapterFilterDownloadedList = []
|
||||
..chapterFilterUnreadList = []
|
||||
..chapterPageUrlsList = []
|
||||
..chapterPageIndexList = []
|
||||
..cookiesList = []);
|
||||
},
|
||||
);
|
||||
}
|
||||
await Hive.openBox(HiveConstant.hiveBoxAppSettings);
|
||||
await Hive.openBox(HiveConstant.hiveBoxMangaInfo);
|
||||
}
|
||||
|
||||
_iniDateFormatting() {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,150 @@
|
|||
// import 'package:isar/isar.dart';
|
||||
// import 'package:mangayomi/models/chapter.dart';
|
||||
// part 'settings.g.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
part 'settings.g.dart';
|
||||
|
||||
// @collection
|
||||
// @Name("Settings")
|
||||
// class Settings {
|
||||
// Id? id;
|
||||
// int? mangaId;
|
||||
|
||||
// String? date;
|
||||
// Settings({
|
||||
// this.id = 227,
|
||||
// required this.mangaId,
|
||||
// required this.date,
|
||||
// });
|
||||
// }
|
||||
@collection
|
||||
@Name("Settings")
|
||||
class Settings {
|
||||
Id? id;
|
||||
|
||||
@enumerated
|
||||
DisplayType displayType;
|
||||
|
||||
int? libraryFilterMangasDownloadType;
|
||||
|
||||
int? libraryFilterMangasUnreadType;
|
||||
|
||||
int? libraryFilterMangasStartedType;
|
||||
|
||||
int? libraryFilterMangasBookMarkedType;
|
||||
|
||||
bool? libraryShowCategoryTabs;
|
||||
|
||||
bool? libraryDownloadedChapters;
|
||||
|
||||
bool? libraryShowLanguage;
|
||||
|
||||
bool? libraryShowNumbersOfItems;
|
||||
|
||||
bool? libraryShowContinueReadingButton;
|
||||
|
||||
SortLibraryManga? sortLibraryManga;
|
||||
|
||||
List<SortChapter>? sortChapterList;
|
||||
|
||||
List<ChapterFilterDownloaded>? chapterFilterDownloadedList;
|
||||
|
||||
List<ChapterFilterUnread>? chapterFilterUnreadList;
|
||||
|
||||
List<ChapterFilterBookmarked>? chapterFilterBookmarkedList;
|
||||
|
||||
double? flexColorSchemeBlendLevel;
|
||||
|
||||
String? dateFormat;
|
||||
|
||||
int? relativeTimesTamps;
|
||||
|
||||
int? flexSchemeColorIndex;
|
||||
|
||||
bool? themeIsDark;
|
||||
|
||||
bool? incognitoMode;
|
||||
|
||||
List<ChapterPageurls>? chapterPageUrlsList;
|
||||
|
||||
bool? showPagesNumber;
|
||||
|
||||
List<ChapterPageIndex>? chapterPageIndexList;
|
||||
|
||||
String? userAgent;
|
||||
|
||||
List<Cookie>? cookiesList;
|
||||
|
||||
Settings(
|
||||
{this.id = 227,
|
||||
this.displayType = DisplayType.compactGrid,
|
||||
this.libraryFilterMangasDownloadType = 0,
|
||||
this.libraryFilterMangasUnreadType = 0,
|
||||
this.libraryFilterMangasStartedType = 0,
|
||||
this.libraryFilterMangasBookMarkedType = 0,
|
||||
this.libraryShowCategoryTabs = false,
|
||||
this.libraryDownloadedChapters = false,
|
||||
this.libraryShowLanguage = false,
|
||||
this.libraryShowNumbersOfItems = false,
|
||||
this.libraryShowContinueReadingButton = false,
|
||||
this.sortLibraryManga,
|
||||
this.sortChapterList,
|
||||
this.chapterFilterDownloadedList,
|
||||
this.flexColorSchemeBlendLevel = 10.0,
|
||||
this.dateFormat = "M/d/y",
|
||||
this.relativeTimesTamps = 2,
|
||||
this.flexSchemeColorIndex = 2,
|
||||
this.themeIsDark = true,
|
||||
this.incognitoMode = false,
|
||||
this.chapterPageUrlsList,
|
||||
this.showPagesNumber = true,
|
||||
this.chapterPageIndexList,
|
||||
this.userAgent = defaultUserAgent,
|
||||
this.cookiesList});
|
||||
}
|
||||
|
||||
enum DisplayType {
|
||||
compactGrid,
|
||||
comfortableGrid,
|
||||
coverOnlyGrid,
|
||||
list,
|
||||
}
|
||||
|
||||
@embedded
|
||||
class SortLibraryManga {
|
||||
bool? reverse;
|
||||
int? index;
|
||||
SortLibraryManga({this.reverse = false, this.index = 0});
|
||||
}
|
||||
|
||||
@embedded
|
||||
class SortChapter {
|
||||
int? mangaId;
|
||||
bool? reverse;
|
||||
int? index;
|
||||
SortChapter({this.mangaId, this.reverse = false, this.index = 1});
|
||||
}
|
||||
|
||||
@embedded
|
||||
class ChapterFilterDownloaded {
|
||||
int? mangaId;
|
||||
int? type;
|
||||
ChapterFilterDownloaded({this.mangaId, this.type = 0});
|
||||
}
|
||||
|
||||
@embedded
|
||||
class ChapterFilterUnread {
|
||||
int? mangaId;
|
||||
int? type;
|
||||
ChapterFilterUnread({this.mangaId, this.type = 0});
|
||||
}
|
||||
|
||||
@embedded
|
||||
class ChapterFilterBookmarked {
|
||||
int? mangaId;
|
||||
int? type;
|
||||
ChapterFilterBookmarked({this.mangaId, this.type = 0});
|
||||
}
|
||||
|
||||
@embedded
|
||||
class ChapterPageurls {
|
||||
int? chapterId;
|
||||
List<String>? urls;
|
||||
}
|
||||
|
||||
@embedded
|
||||
class ChapterPageIndex {
|
||||
int? chapterId;
|
||||
int? index;
|
||||
}
|
||||
|
||||
@embedded
|
||||
class Cookie {
|
||||
String? source;
|
||||
String? cookie;
|
||||
}
|
||||
|
|
|
|||
5592
lib/models/settings.g.dart
Normal file
5592
lib/models/settings.g.dart
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,17 +0,0 @@
|
|||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'hive_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
Box hiveBoxManga(HiveBoxMangaRef ref) {
|
||||
return Hive.box(HiveConstant.hiveBoxMangaInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@riverpod
|
||||
Box hiveBoxSettings(HiveBoxSettingsRef ref) {
|
||||
return Hive.box(HiveConstant.hiveBoxAppSettings);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'hive_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$hiveBoxMangaHash() => r'c33563594027369f6f2f83fad7e5279c676ef157';
|
||||
|
||||
/// See also [hiveBoxManga].
|
||||
@ProviderFor(hiveBoxManga)
|
||||
final hiveBoxMangaProvider = AutoDisposeProvider<Box<dynamic>>.internal(
|
||||
hiveBoxManga,
|
||||
name: r'hiveBoxMangaProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$hiveBoxMangaHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef HiveBoxMangaRef = AutoDisposeProviderRef<Box<dynamic>>;
|
||||
String _$hiveBoxSettingsHash() => r'3e948a0ae8fc23d691aeb3e39032007b07f33290';
|
||||
|
||||
/// See also [hiveBoxSettings].
|
||||
@ProviderFor(hiveBoxSettings)
|
||||
final hiveBoxSettingsProvider = AutoDisposeProvider<Box<dynamic>>.internal(
|
||||
hiveBoxSettings,
|
||||
name: r'hiveBoxSettingsProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$hiveBoxSettingsHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef HiveBoxSettingsRef = AutoDisposeProviderRef<Box<dynamic>>;
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -5,6 +5,7 @@ import 'package:path_provider/path_provider.dart';
|
|||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class StorageProvider {
|
||||
RegExp regExpChar = RegExp(r'[^a-zA-Z0-9 .()\-\s]');
|
||||
Future<bool> requestPermission() async {
|
||||
Permission permission = Permission.manageExternalStorage;
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
|
|
@ -38,17 +39,17 @@ class StorageProvider {
|
|||
) async {
|
||||
final manga = chapter.manga.value!;
|
||||
String scanlator = chapter.scanlator!.isNotEmpty
|
||||
? "${chapter.scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
? "${chapter.scanlator!.replaceAll(regExpChar, '_')}_"
|
||||
: "";
|
||||
final dir = await getDirectory();
|
||||
return Directory(
|
||||
"${dir!.path}/downloads/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${chapter.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
"${dir!.path}/downloads/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(regExpChar, '_')}/$scanlator${chapter.name!.replaceAll(regExpChar, '_')}/");
|
||||
}
|
||||
|
||||
Future<Directory?> getMangaMainDirectory(Chapter chapter) async {
|
||||
final manga = chapter.manga.value!;
|
||||
final dir = await getDirectory();
|
||||
return Directory(
|
||||
"${dir!.path}/downloads/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
"${dir!.path}/downloads/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(regExpChar, '_')}/");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// ignore_for_file: depend_o
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
|
||||
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
|
||||
|
|
@ -20,7 +21,7 @@ part 'get_chapter_url.g.dart';
|
|||
|
||||
class GetChapterUrlModel {
|
||||
Directory? path;
|
||||
List pageUrls = [];
|
||||
List<String> pageUrls = [];
|
||||
List<bool> isLocaleList = [];
|
||||
GetChapterUrlModel(
|
||||
{required this.path, required this.pageUrls, required this.isLocaleList});
|
||||
|
|
@ -32,18 +33,20 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
required Chapter chapter,
|
||||
}) async {
|
||||
Directory? path;
|
||||
List pageUrls = [];
|
||||
List<String> pageUrls = [];
|
||||
final manga = chapter.manga.value!;
|
||||
List<bool> isLocaleList = [];
|
||||
String source = manga.source!.toLowerCase();
|
||||
List hivePagesUrls = ref.watch(hiveBoxMangaProvider).get(
|
||||
"${manga.lang}-${manga.source}/${manga.name}/${chapter.name}-pageurl",
|
||||
defaultValue: []);
|
||||
final settings = isar.settings.getSync(227);
|
||||
final isarPageUrls = settings!.chapterPageUrlsList!
|
||||
.where((element) => element.chapterId == chapter.id);
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
path = await StorageProvider().getMangaChapterDirectory(chapter);
|
||||
|
||||
if (hivePagesUrls.isNotEmpty) {
|
||||
pageUrls = hivePagesUrls;
|
||||
if (isarPageUrls.isNotEmpty &&
|
||||
isarPageUrls.first.urls != null &&
|
||||
isarPageUrls.first.urls!.isNotEmpty) {
|
||||
pageUrls = isarPageUrls.first.urls!;
|
||||
}
|
||||
|
||||
/*********/
|
||||
|
|
@ -51,7 +54,7 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/********/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.comick) {
|
||||
pageUrls = await Comick().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await Comick().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
/*************/
|
||||
|
|
@ -59,7 +62,7 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/**************/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
|
||||
pageUrls = await MangaThemeSia().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await MangaThemeSia().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -67,7 +70,7 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/***********/
|
||||
|
||||
else if (source == 'mangakawaii') {
|
||||
pageUrls = await MangaKawaii().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await MangaKawaii().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -75,7 +78,7 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/***********/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
|
||||
pageUrls = await Mmrcms().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await Mmrcms().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -83,7 +86,7 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/***********/
|
||||
|
||||
else if (source == 'mangahere') {
|
||||
pageUrls = await Mangahere().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await Mangahere().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -91,7 +94,7 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/***********/
|
||||
|
||||
else if (source == 'japscan') {
|
||||
pageUrls = await Japscan().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await Japscan().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -99,14 +102,22 @@ Future<GetChapterUrlModel> getChapterUrl(
|
|||
/***********/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.heancms) {
|
||||
pageUrls = await HeanCms().getChapterUrl(chapter: chapter);
|
||||
pageUrls = await HeanCms().getChapterUrl(chapter: chapter, ref: ref);
|
||||
}
|
||||
|
||||
if (pageUrls.isNotEmpty) {
|
||||
if (!incognitoMode) {
|
||||
ref.watch(hiveBoxMangaProvider).put(
|
||||
"${manga.lang}-${manga.source}/${manga.name}/${chapter.name}-pageurl",
|
||||
pageUrls);
|
||||
List<ChapterPageurls>? chapterPageUrls = [];
|
||||
for (var chapterPageUrl in settings.chapterPageUrlsList!) {
|
||||
if (chapterPageUrl.chapterId != chapter.id) {
|
||||
chapterPageUrls.add(chapterPageUrl);
|
||||
}
|
||||
}
|
||||
chapterPageUrls.add(ChapterPageurls()
|
||||
..chapterId = chapter.id
|
||||
..urls = pageUrls);
|
||||
isar.writeTxnSync(() => isar.settings
|
||||
.putSync(settings..chapterPageUrlsList = chapterPageUrls));
|
||||
}
|
||||
for (var i = 0; i < pageUrls.length; i++) {
|
||||
if (await File("${path!.path}" "${padIndex(i + 1)}.jpg").exists()) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'get_chapter_url.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$getChapterUrlHash() => r'a13c39db0b03f5c1575c94f76b24676ebaa4e3c6';
|
||||
String _$getChapterUrlHash() => r'7713a0aa89a528cf9aa90016fdebb63af89a2520';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
|
|||
/********/
|
||||
|
||||
if (getMangaTypeSource(source.toLowerCase()) == TypeSource.comick) {
|
||||
mangadetail =
|
||||
await Comick().getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
mangadetail = await Comick()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
/*************/
|
||||
/*mangathemesia*/
|
||||
|
|
@ -33,14 +33,14 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
|
|||
|
||||
if (getMangaTypeSource(source.toLowerCase()) == TypeSource.mangathemesia) {
|
||||
mangadetail = await MangaThemeSia()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
/***********/
|
||||
/*mangakawaii*/
|
||||
/***********/
|
||||
else if (source.toLowerCase() == "mangakawaii") {
|
||||
mangadetail = await MangaKawaii()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -48,8 +48,8 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
|
|||
/***********/
|
||||
|
||||
else if (getMangaTypeSource(source.toLowerCase()) == TypeSource.mmrcms) {
|
||||
mangadetail =
|
||||
await Mmrcms().getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
mangadetail = await Mmrcms()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -57,7 +57,7 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
|
|||
/***********/
|
||||
else if (source.toLowerCase() == "mangahere") {
|
||||
mangadetail = await Mangahere()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -66,7 +66,7 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
|
|||
|
||||
else if (source.toLowerCase() == "japscan") {
|
||||
mangadetail = await Japscan()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -75,7 +75,7 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
|
|||
|
||||
else if (getMangaTypeSource(source.toLowerCase()) == TypeSource.heancms) {
|
||||
mangadetail = await HeanCms()
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source);
|
||||
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
|
||||
}
|
||||
return mangadetail!;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'get_manga_detail.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$getMangaDetailHash() => r'a4e94e2023998f08d6c617ba26e56069cd89882a';
|
||||
String _$getMangaDetailHash() => r'938a051244e585f8350f95556bd3f94b9d0145c4';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -22,23 +22,24 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
|
|||
/*comick*/
|
||||
/*******/
|
||||
if (getMangaTypeSource(source) == TypeSource.comick) {
|
||||
popularManga = await Comick().getPopularManga(source: source, page: page);
|
||||
popularManga =
|
||||
await Comick().getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
|
||||
/***************/
|
||||
/*mangathemesia*/
|
||||
/**************/
|
||||
if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
|
||||
popularManga =
|
||||
await MangaThemeSia().getPopularManga(source: source, page: page);
|
||||
popularManga = await MangaThemeSia()
|
||||
.getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
/*mangakawaii*/
|
||||
/***********/
|
||||
if (source == "mangakawaii") {
|
||||
popularManga =
|
||||
await MangaKawaii().getPopularManga(source: source, page: page);
|
||||
popularManga = await MangaKawaii()
|
||||
.getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -46,7 +47,8 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
|
|||
/***********/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
|
||||
popularManga = await Mmrcms().getPopularManga(source: source, page: page);
|
||||
popularManga =
|
||||
await Mmrcms().getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -54,20 +56,22 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
|
|||
/***********/
|
||||
else if (source == "mangahere") {
|
||||
popularManga =
|
||||
await Mangahere().getPopularManga(source: source, page: page);
|
||||
await Mangahere().getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
/***********/
|
||||
/*japscan*/
|
||||
/***********/
|
||||
else if (source == "japscan") {
|
||||
popularManga = await Japscan().getPopularManga(source: source, page: page);
|
||||
popularManga =
|
||||
await Japscan().getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
/*japscan*/
|
||||
/***********/
|
||||
else if (getMangaTypeSource(source) == TypeSource.heancms) {
|
||||
popularManga = await HeanCms().getPopularManga(source: source, page: page);
|
||||
popularManga =
|
||||
await HeanCms().getPopularManga(source: source, page: page, ref: ref);
|
||||
}
|
||||
return popularManga!;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'get_popular_manga.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$getPopularMangaHash() => r'09e78df804d440b2ab9777aab28bdc75f64f7fac';
|
||||
String _$getPopularMangaHash() => r'27240e2756f6bd99d44a553ddd7ebe4374618c8d';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:html/dom.dart' as dom;
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/services/http_service/cloudflare/cookie.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'cloudflare_bypass.g.dart';
|
||||
|
||||
Future<dom.Document?> cloudflareBypassDom(
|
||||
@riverpod
|
||||
Future<dom.Document?> cloudflareBypassDom(CloudflareBypassDomRef ref,
|
||||
{required String url,
|
||||
required String source,
|
||||
required bool useUserAgent}) async {
|
||||
// log(source);
|
||||
bool isOk = false;
|
||||
dom.Document? htmll;
|
||||
final ua = Hive.box(HiveConstant.hiveBoxAppSettings)
|
||||
.get("ua", defaultValue: defaultUserAgent);
|
||||
final ua = isar.settings.getSync(227)!.userAgent!;
|
||||
HeadlessInAppWebView? headlessWebViewJapScan;
|
||||
headlessWebViewJapScan = HeadlessInAppWebView(
|
||||
onLoadStop: (controller, u) async {
|
||||
|
|
@ -51,16 +54,16 @@ Future<dom.Document?> cloudflareBypassDom(
|
|||
}
|
||||
return true;
|
||||
});
|
||||
await setCookie(source, url);
|
||||
await ref.watch(setCookieProvider(source, url).future);
|
||||
return htmll;
|
||||
}
|
||||
|
||||
Future<String> cloudflareBypassHtml(
|
||||
@riverpod
|
||||
Future<String> cloudflareBypassHtml(CloudflareBypassHtmlRef ref,
|
||||
{required String url,
|
||||
required String source,
|
||||
required bool useUserAgent}) async {
|
||||
final ua = Hive.box(HiveConstant.hiveBoxAppSettings)
|
||||
.get("ua", defaultValue: defaultUserAgent);
|
||||
final ua = isar.settings.getSync(227)!.userAgent!;
|
||||
bool isOk = false;
|
||||
String? html;
|
||||
HeadlessInAppWebView? headlessWebViewJapScan;
|
||||
|
|
@ -98,6 +101,6 @@ Future<String> cloudflareBypassHtml(
|
|||
}
|
||||
return true;
|
||||
});
|
||||
await setCookie(source, url);
|
||||
await ref.watch(setCookieProvider(source, url).future);
|
||||
return html!;
|
||||
}
|
||||
|
|
|
|||
230
lib/services/http_service/cloudflare/cloudflare_bypass.g.dart
Normal file
230
lib/services/http_service/cloudflare/cloudflare_bypass.g.dart
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'cloudflare_bypass.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$cloudflareBypassDomHash() =>
|
||||
r'f1307097afd3dd52318ecd83a4a979f4a6711aa2';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
typedef CloudflareBypassDomRef = AutoDisposeFutureProviderRef<Document?>;
|
||||
|
||||
/// See also [cloudflareBypassDom].
|
||||
@ProviderFor(cloudflareBypassDom)
|
||||
const cloudflareBypassDomProvider = CloudflareBypassDomFamily();
|
||||
|
||||
/// See also [cloudflareBypassDom].
|
||||
class CloudflareBypassDomFamily extends Family<AsyncValue<Document?>> {
|
||||
/// See also [cloudflareBypassDom].
|
||||
const CloudflareBypassDomFamily();
|
||||
|
||||
/// See also [cloudflareBypassDom].
|
||||
CloudflareBypassDomProvider call({
|
||||
required String url,
|
||||
required String source,
|
||||
required bool useUserAgent,
|
||||
}) {
|
||||
return CloudflareBypassDomProvider(
|
||||
url: url,
|
||||
source: source,
|
||||
useUserAgent: useUserAgent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
CloudflareBypassDomProvider getProviderOverride(
|
||||
covariant CloudflareBypassDomProvider provider,
|
||||
) {
|
||||
return call(
|
||||
url: provider.url,
|
||||
source: provider.source,
|
||||
useUserAgent: provider.useUserAgent,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'cloudflareBypassDomProvider';
|
||||
}
|
||||
|
||||
/// See also [cloudflareBypassDom].
|
||||
class CloudflareBypassDomProvider extends AutoDisposeFutureProvider<Document?> {
|
||||
/// See also [cloudflareBypassDom].
|
||||
CloudflareBypassDomProvider({
|
||||
required this.url,
|
||||
required this.source,
|
||||
required this.useUserAgent,
|
||||
}) : super.internal(
|
||||
(ref) => cloudflareBypassDom(
|
||||
ref,
|
||||
url: url,
|
||||
source: source,
|
||||
useUserAgent: useUserAgent,
|
||||
),
|
||||
from: cloudflareBypassDomProvider,
|
||||
name: r'cloudflareBypassDomProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$cloudflareBypassDomHash,
|
||||
dependencies: CloudflareBypassDomFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
CloudflareBypassDomFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String url;
|
||||
final String source;
|
||||
final bool useUserAgent;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is CloudflareBypassDomProvider &&
|
||||
other.url == url &&
|
||||
other.source == source &&
|
||||
other.useUserAgent == useUserAgent;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, url.hashCode);
|
||||
hash = _SystemHash.combine(hash, source.hashCode);
|
||||
hash = _SystemHash.combine(hash, useUserAgent.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
String _$cloudflareBypassHtmlHash() =>
|
||||
r'eb50578058f3b316fa07a01e336281931af55afb';
|
||||
typedef CloudflareBypassHtmlRef = AutoDisposeFutureProviderRef<String>;
|
||||
|
||||
/// See also [cloudflareBypassHtml].
|
||||
@ProviderFor(cloudflareBypassHtml)
|
||||
const cloudflareBypassHtmlProvider = CloudflareBypassHtmlFamily();
|
||||
|
||||
/// See also [cloudflareBypassHtml].
|
||||
class CloudflareBypassHtmlFamily extends Family<AsyncValue<String>> {
|
||||
/// See also [cloudflareBypassHtml].
|
||||
const CloudflareBypassHtmlFamily();
|
||||
|
||||
/// See also [cloudflareBypassHtml].
|
||||
CloudflareBypassHtmlProvider call({
|
||||
required String url,
|
||||
required String source,
|
||||
required bool useUserAgent,
|
||||
}) {
|
||||
return CloudflareBypassHtmlProvider(
|
||||
url: url,
|
||||
source: source,
|
||||
useUserAgent: useUserAgent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
CloudflareBypassHtmlProvider getProviderOverride(
|
||||
covariant CloudflareBypassHtmlProvider provider,
|
||||
) {
|
||||
return call(
|
||||
url: provider.url,
|
||||
source: provider.source,
|
||||
useUserAgent: provider.useUserAgent,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'cloudflareBypassHtmlProvider';
|
||||
}
|
||||
|
||||
/// See also [cloudflareBypassHtml].
|
||||
class CloudflareBypassHtmlProvider extends AutoDisposeFutureProvider<String> {
|
||||
/// See also [cloudflareBypassHtml].
|
||||
CloudflareBypassHtmlProvider({
|
||||
required this.url,
|
||||
required this.source,
|
||||
required this.useUserAgent,
|
||||
}) : super.internal(
|
||||
(ref) => cloudflareBypassHtml(
|
||||
ref,
|
||||
url: url,
|
||||
source: source,
|
||||
useUserAgent: useUserAgent,
|
||||
),
|
||||
from: cloudflareBypassHtmlProvider,
|
||||
name: r'cloudflareBypassHtmlProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$cloudflareBypassHtmlHash,
|
||||
dependencies: CloudflareBypassHtmlFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
CloudflareBypassHtmlFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String url;
|
||||
final String source;
|
||||
final bool useUserAgent;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is CloudflareBypassHtmlProvider &&
|
||||
other.url == url &&
|
||||
other.source == source &&
|
||||
other.useUserAgent == useUserAgent;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, url.hashCode);
|
||||
hash = _SystemHash.combine(hash, source.hashCode);
|
||||
hash = _SystemHash.combine(hash, useUserAgent.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -1,22 +1,23 @@
|
|||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:mangayomi/services/http_service/cloudflare/providers/cookie_providers.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'cookie.g.dart';
|
||||
|
||||
setCookie(String source, String url) async {
|
||||
@riverpod
|
||||
Future setCookie(SetCookieRef ref, String source, String url) async {
|
||||
source = source.toLowerCase();
|
||||
final hiveSetting = Hive.box(HiveConstant.hiveBoxAppSettings);
|
||||
final cookieS = ref.watch(cookieStateProvider(source));
|
||||
|
||||
List<Cookie> cookies = [];
|
||||
CookieManager cookie = CookieManager.instance();
|
||||
cookies = await cookie.getCookies(url: WebUri.uri(Uri.parse(url.toString())));
|
||||
final cfClearance =
|
||||
cookies.where((element) => element.name == "cf_clearance").toList();
|
||||
String newCookie = "";
|
||||
if (cfClearance.isNotEmpty &&
|
||||
cfClearance.first.name !=
|
||||
hiveSetting.get("$source-cookie", defaultValue: "")) {
|
||||
if (cfClearance.isNotEmpty && cfClearance.first.name != cookieS) {
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
newCookie = "$newCookie ${cookies[i].name}=${cookies[i].value};";
|
||||
}
|
||||
hiveSetting.put("$source-cookie", newCookie);
|
||||
ref.read(cookieStateProvider(source).notifier).setCookie(newCookie);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
120
lib/services/http_service/cloudflare/cookie.g.dart
Normal file
120
lib/services/http_service/cloudflare/cookie.g.dart
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'cookie.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$setCookieHash() => r'e9519081f85b28e34d09466392e4e253cc51b9af';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
typedef SetCookieRef = AutoDisposeFutureProviderRef<dynamic>;
|
||||
|
||||
/// See also [setCookie].
|
||||
@ProviderFor(setCookie)
|
||||
const setCookieProvider = SetCookieFamily();
|
||||
|
||||
/// See also [setCookie].
|
||||
class SetCookieFamily extends Family<AsyncValue<dynamic>> {
|
||||
/// See also [setCookie].
|
||||
const SetCookieFamily();
|
||||
|
||||
/// See also [setCookie].
|
||||
SetCookieProvider call(
|
||||
String source,
|
||||
String url,
|
||||
) {
|
||||
return SetCookieProvider(
|
||||
source,
|
||||
url,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
SetCookieProvider getProviderOverride(
|
||||
covariant SetCookieProvider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.source,
|
||||
provider.url,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'setCookieProvider';
|
||||
}
|
||||
|
||||
/// See also [setCookie].
|
||||
class SetCookieProvider extends AutoDisposeFutureProvider<dynamic> {
|
||||
/// See also [setCookie].
|
||||
SetCookieProvider(
|
||||
this.source,
|
||||
this.url,
|
||||
) : super.internal(
|
||||
(ref) => setCookie(
|
||||
ref,
|
||||
source,
|
||||
url,
|
||||
),
|
||||
from: setCookieProvider,
|
||||
name: r'setCookieProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$setCookieHash,
|
||||
dependencies: SetCookieFamily._dependencies,
|
||||
allTransitiveDependencies: SetCookieFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String source;
|
||||
final String url;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is SetCookieProvider &&
|
||||
other.source == source &&
|
||||
other.url == url;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, source.hashCode);
|
||||
hash = _SystemHash.combine(hash, url.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'cookie_providers.g.dart';
|
||||
|
||||
@riverpod
|
||||
class CookieState extends _$CookieState {
|
||||
@override
|
||||
String build(String source) {
|
||||
final cookieList = isar.settings
|
||||
.getSync(227)!
|
||||
.cookiesList!
|
||||
.where((element) => element.source == source);
|
||||
String cookie = "";
|
||||
if (cookieList.isNotEmpty) {
|
||||
cookie = cookieList.first.cookie!;
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
void setCookie(String newCookie) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
List<Cookie>? cookieList = [];
|
||||
for (var cookie in settings!.cookiesList!) {
|
||||
if (cookie.source != source) {
|
||||
cookieList.add(cookie);
|
||||
}
|
||||
}
|
||||
cookieList.add(Cookie()
|
||||
..source = source
|
||||
..cookie = newCookie);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings..cookiesList = cookieList));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'cookie_providers.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$cookieStateHash() => r'1ae831fd859a7f084f26be985ebf1e126b38a788';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$CookieState extends BuildlessAutoDisposeNotifier<String> {
|
||||
late final String source;
|
||||
|
||||
String build(
|
||||
String source,
|
||||
);
|
||||
}
|
||||
|
||||
/// See also [CookieState].
|
||||
@ProviderFor(CookieState)
|
||||
const cookieStateProvider = CookieStateFamily();
|
||||
|
||||
/// See also [CookieState].
|
||||
class CookieStateFamily extends Family<String> {
|
||||
/// See also [CookieState].
|
||||
const CookieStateFamily();
|
||||
|
||||
/// See also [CookieState].
|
||||
CookieStateProvider call(
|
||||
String source,
|
||||
) {
|
||||
return CookieStateProvider(
|
||||
source,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
CookieStateProvider getProviderOverride(
|
||||
covariant CookieStateProvider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.source,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'cookieStateProvider';
|
||||
}
|
||||
|
||||
/// See also [CookieState].
|
||||
class CookieStateProvider
|
||||
extends AutoDisposeNotifierProviderImpl<CookieState, String> {
|
||||
/// See also [CookieState].
|
||||
CookieStateProvider(
|
||||
this.source,
|
||||
) : super.internal(
|
||||
() => CookieState()..source = source,
|
||||
from: cookieStateProvider,
|
||||
name: r'cookieStateProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$cookieStateHash,
|
||||
dependencies: CookieStateFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
CookieStateFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String source;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is CookieStateProvider && other.source == source;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, source.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
|
||||
@override
|
||||
String runNotifierBuild(
|
||||
covariant CookieState notifier,
|
||||
) {
|
||||
return notifier.build(
|
||||
source,
|
||||
);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -4,8 +4,11 @@ import 'package:mangayomi/services/http_service/http_res_to_dom_html.dart';
|
|||
import 'package:http/http.dart' as http;
|
||||
import 'package:mangayomi/sources/utils/utils.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'http_service.g.dart';
|
||||
|
||||
Future<dynamic> httpGet(
|
||||
@riverpod
|
||||
Future<dynamic> httpGet(HttpGetRef ref,
|
||||
{required String url,
|
||||
required String source,
|
||||
required bool resDom,
|
||||
|
|
@ -14,24 +17,24 @@ Future<dynamic> httpGet(
|
|||
if (resDom) {
|
||||
Document? dom;
|
||||
if (isCloudflaree) {
|
||||
dom = await cloudflareBypassDom(
|
||||
url: url, source: source, useUserAgent: useUserAgent);
|
||||
dom = await ref.read(cloudflareBypassDomProvider(
|
||||
url: url, source: source, useUserAgent: useUserAgent)
|
||||
.future);
|
||||
} else {
|
||||
dom = await httpResToDom(url: url, headers: headers(source));
|
||||
dom = await httpResToDom(
|
||||
url: url, headers: ref.watch(headersProvider(source: source)));
|
||||
}
|
||||
return dom;
|
||||
} else {
|
||||
String? resHtml;
|
||||
if (isCloudflaree) {
|
||||
resHtml = await cloudflareBypassHtml(
|
||||
url: url,
|
||||
source: source,
|
||||
useUserAgent: useUserAgent,
|
||||
);
|
||||
resHtml = await ref.read(cloudflareBypassHtmlProvider(
|
||||
url: url, source: source, useUserAgent: useUserAgent)
|
||||
.future);
|
||||
} else {
|
||||
try {
|
||||
final response =
|
||||
await http.get(Uri.parse(url), headers: headers(source));
|
||||
final response = await http.get(Uri.parse(url),
|
||||
headers: ref.watch(headersProvider(source: source)));
|
||||
resHtml = response.body;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
|
|
|
|||
136
lib/services/http_service/http_service.g.dart
Normal file
136
lib/services/http_service/http_service.g.dart
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'http_service.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$httpGetHash() => r'57b50256bd7577a4d795cf74f9429d3a4434792f';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
typedef HttpGetRef = AutoDisposeFutureProviderRef<dynamic>;
|
||||
|
||||
/// See also [httpGet].
|
||||
@ProviderFor(httpGet)
|
||||
const httpGetProvider = HttpGetFamily();
|
||||
|
||||
/// See also [httpGet].
|
||||
class HttpGetFamily extends Family<AsyncValue<dynamic>> {
|
||||
/// See also [httpGet].
|
||||
const HttpGetFamily();
|
||||
|
||||
/// See also [httpGet].
|
||||
HttpGetProvider call({
|
||||
required String url,
|
||||
required String source,
|
||||
required bool resDom,
|
||||
bool useUserAgent = false,
|
||||
}) {
|
||||
return HttpGetProvider(
|
||||
url: url,
|
||||
source: source,
|
||||
resDom: resDom,
|
||||
useUserAgent: useUserAgent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
HttpGetProvider getProviderOverride(
|
||||
covariant HttpGetProvider provider,
|
||||
) {
|
||||
return call(
|
||||
url: provider.url,
|
||||
source: provider.source,
|
||||
resDom: provider.resDom,
|
||||
useUserAgent: provider.useUserAgent,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'httpGetProvider';
|
||||
}
|
||||
|
||||
/// See also [httpGet].
|
||||
class HttpGetProvider extends AutoDisposeFutureProvider<dynamic> {
|
||||
/// See also [httpGet].
|
||||
HttpGetProvider({
|
||||
required this.url,
|
||||
required this.source,
|
||||
required this.resDom,
|
||||
this.useUserAgent = false,
|
||||
}) : super.internal(
|
||||
(ref) => httpGet(
|
||||
ref,
|
||||
url: url,
|
||||
source: source,
|
||||
resDom: resDom,
|
||||
useUserAgent: useUserAgent,
|
||||
),
|
||||
from: httpGetProvider,
|
||||
name: r'httpGetProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$httpGetHash,
|
||||
dependencies: HttpGetFamily._dependencies,
|
||||
allTransitiveDependencies: HttpGetFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String url;
|
||||
final String source;
|
||||
final bool resDom;
|
||||
final bool useUserAgent;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is HttpGetProvider &&
|
||||
other.url == url &&
|
||||
other.source == source &&
|
||||
other.resDom == resDom &&
|
||||
other.useUserAgent == useUserAgent;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, url.hashCode);
|
||||
hash = _SystemHash.combine(hash, source.hashCode);
|
||||
hash = _SystemHash.combine(hash, resDom.hashCode);
|
||||
hash = _SystemHash.combine(hash, useUserAgent.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -22,7 +22,7 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/********/
|
||||
|
||||
if (getMangaTypeSource(source) == TypeSource.comick) {
|
||||
manga = await Comick().searchManga(source: source, query: query);
|
||||
manga = await Comick().searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
/***************/
|
||||
|
|
@ -30,7 +30,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/***************/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
|
||||
manga = await MangaThemeSia().searchManga(source: source, query: query);
|
||||
manga = await MangaThemeSia()
|
||||
.searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -38,7 +39,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/***********/
|
||||
|
||||
else if (source == "mangakawaii") {
|
||||
manga = await MangaKawaii().searchManga(source: source, query: query);
|
||||
manga =
|
||||
await MangaKawaii().searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -46,7 +48,7 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/***********/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
|
||||
manga = await Mmrcms().searchManga(source: source, query: query);
|
||||
manga = await Mmrcms().searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -54,7 +56,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/***********/
|
||||
|
||||
else if (source == "mangahere") {
|
||||
manga = await Mangahere().searchManga(source: source, query: query);
|
||||
manga =
|
||||
await Mangahere().searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -62,7 +65,7 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/***********/
|
||||
|
||||
else if (source == "japscan") {
|
||||
manga = await Japscan().searchManga(source: source, query: query);
|
||||
manga = await Japscan().searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
/***********/
|
||||
|
|
@ -70,7 +73,7 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
|
|||
/***********/
|
||||
|
||||
else if (getMangaTypeSource(source) == TypeSource.heancms) {
|
||||
manga = await HeanCms().searchManga(source: source, query: query);
|
||||
manga = await HeanCms().searchManga(source: source, query: query, ref: ref);
|
||||
}
|
||||
|
||||
return manga!;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'search_manga.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$searchMangaHash() => r'4f5160d862404936b098269fe913bda960deb039';
|
||||
String _$searchMangaHash() => r'0d71677c6ef2822590f2061119134e3b0e3167f7';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/services/http_service/cloudflare/cookie.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class MangaWebView extends ConsumerStatefulWidget {
|
||||
|
|
@ -132,16 +132,14 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
});
|
||||
},
|
||||
onUpdateVisitedHistory: (controller, url, isReload) async {
|
||||
await setCookie(widget.source, url.toString());
|
||||
await ref.watch(
|
||||
setCookieProvider(widget.source, url.toString()).future);
|
||||
setState(() {
|
||||
_url = url.toString();
|
||||
});
|
||||
},
|
||||
initialSettings: InAppWebViewSettings(
|
||||
userAgent: Hive.box(HiveConstant.hiveBoxAppSettings).get(
|
||||
"ua",
|
||||
defaultValue:
|
||||
defaultUserAgent)),
|
||||
userAgent: isar.settings.getSync(227)!.userAgent!),
|
||||
initialUrlRequest:
|
||||
URLRequest(url: WebUri.uri(Uri.parse(widget.url))),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:convert';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/services/http_service/http_res_to_dom_html.dart';
|
||||
import 'package:mangayomi/sources/multisrc/heancms/model/search.dart';
|
||||
|
|
@ -15,7 +16,9 @@ class HeanCms extends MangaYomiServices {
|
|||
'Content-Type': 'application/json'
|
||||
};
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final chapterId = chapter.url!.split("#").last;
|
||||
var request = http.Request(
|
||||
'GET',
|
||||
|
|
@ -41,7 +44,8 @@ class HeanCms extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
String currentSlug = manga.url!.split('/').last;
|
||||
|
||||
var request = http.Request(
|
||||
|
|
@ -54,7 +58,7 @@ class HeanCms extends MangaYomiServices {
|
|||
http.StreamedResponse response = await request.send();
|
||||
final res = await response.stream.bytesToString();
|
||||
var mangaDetail = jsonDecode(res) as Map<String, dynamic>;
|
||||
|
||||
|
||||
final d = Data.fromJson(mangaDetail);
|
||||
|
||||
final dom = await httpResToDom(
|
||||
|
|
@ -89,7 +93,9 @@ class HeanCms extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
var request = http.Request(
|
||||
'POST', Uri.parse('${getMangaAPIUrl(source)}series/querysearch'));
|
||||
request.body = json.encode({
|
||||
|
|
@ -127,7 +133,9 @@ class HeanCms extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
var request = http.Request(
|
||||
'POST', Uri.parse('${getMangaAPIUrl(source)}series/search'));
|
||||
request.body = json.encode({"term": query.trim()});
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/sources/service.dart';
|
||||
// import 'package:mangayomi/models/chapter.dart';
|
||||
// import 'package:mangayomi/sources/service.dart';
|
||||
|
||||
class Madara extends MangaYomiServices {
|
||||
@override
|
||||
Future<List?> getChapterUrl({required Chapter chapter}) {
|
||||
// TODO: implement getChapterUrl
|
||||
throw UnimplementedError();
|
||||
}
|
||||
// class Madara extends MangaYomiServices {
|
||||
// @override
|
||||
// Future<List?> getChapterUrl({required Chapter chapter}) {
|
||||
// // TODO: implement getChapterUrl
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
@override
|
||||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga, required String lang, required String source}) {
|
||||
// TODO: implement getMangaDetail
|
||||
throw UnimplementedError();
|
||||
}
|
||||
// @override
|
||||
// Future<GetManga?> getMangaDetail(
|
||||
// {required GetManga manga, required String lang, required String source}) {
|
||||
// // TODO: implement getMangaDetail
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) {
|
||||
// TODO: implement getPopularManga
|
||||
throw UnimplementedError();
|
||||
}
|
||||
// @override
|
||||
// Future<List<GetManga?>> getPopularManga(
|
||||
// {required String source, required int page}) {
|
||||
// // TODO: implement getPopularManga
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) {
|
||||
// TODO: implement searchManga
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
// @override
|
||||
// Future<List<GetManga?>> searchManga(
|
||||
// {required String source, required String query}) {
|
||||
// // TODO: implement searchManga
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/services/http_service/http_service.dart';
|
||||
|
|
@ -9,12 +10,11 @@ class MangaThemeSia extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
final dom = await httpGet(
|
||||
url: manga.url!,
|
||||
source: source,
|
||||
resDom: true,
|
||||
useUserAgent: true) as Document?;
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url: manga.url!, source: source, resDom: true, useUserAgent: true)
|
||||
.future) as Document?;
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
'div.bigcontent, div.animefull, div.main-info, div.postbody')
|
||||
|
|
@ -141,14 +141,17 @@ class MangaThemeSia extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
source = source.toLowerCase();
|
||||
final dom = await httpGet(
|
||||
useUserAgent: true,
|
||||
url:
|
||||
'${getMangaBaseUrl(source)}/manga/?title=&page=$page&order=popular',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
useUserAgent: true,
|
||||
url:
|
||||
'${getMangaBaseUrl(source)}/manga/?title=&page=$page&order=popular',
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
'.utao .uta .imgu, .listupd .bs .bsx, .listo .bs .bsx')
|
||||
|
|
@ -188,11 +191,14 @@ class MangaThemeSia extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
final dom = await httpGet(
|
||||
url: '${getMangaBaseUrl(source)}/?s=${query.trim()}',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url: '${getMangaBaseUrl(source)}/?s=${query.trim()}',
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
'#content > div > div.postbody > div > div.listupd > div > div > a')
|
||||
|
|
@ -222,12 +228,15 @@ class MangaThemeSia extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
final dom = await httpGet(
|
||||
useUserAgent: true,
|
||||
url: chapter.url!,
|
||||
source: "mangathemesia",
|
||||
resDom: true) as Document?;
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
useUserAgent: true,
|
||||
url: chapter.url!,
|
||||
source: "mangathemesia",
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!.querySelectorAll('#readerarea').isNotEmpty) {
|
||||
final ta =
|
||||
dom.querySelectorAll('#readerarea').map((e) => e.outerHtml).toList();
|
||||
|
|
@ -261,7 +270,7 @@ class MangaThemeSia extends MangaYomiServices {
|
|||
}
|
||||
} else if (urls.length > 1 && urls.isNotEmpty) {
|
||||
for (var tt in urls) {
|
||||
pageUrls.add(tt);
|
||||
pageUrls.add(tt!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/services/http_service/http_service.dart';
|
||||
|
|
@ -12,9 +13,11 @@ class Mmrcms extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
final dom = await httpGet(url: manga.url!, source: source, resDom: true)
|
||||
as Document?;
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(
|
||||
httpGetProvider(url: manga.url!, source: source, resDom: true)
|
||||
.future) as Document?;
|
||||
description = dom!
|
||||
.querySelectorAll('.row .well p')
|
||||
.map((e) => e.text.trim())
|
||||
|
|
@ -104,12 +107,15 @@ class Mmrcms extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
final dom = await httpGet(
|
||||
url:
|
||||
'${getMangaBaseUrl(source)}/filterList?page=$page&sortBy=views&asc=false',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'${getMangaBaseUrl(source)}/filterList?page=$page&sortBy=views&asc=false',
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
final urlElement = dom!.getElementsByClassName('chart-title');
|
||||
for (var e in urlElement) {
|
||||
RegExp exp = RegExp(r'href="([^"]+)"');
|
||||
|
|
@ -130,11 +136,14 @@ class Mmrcms extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
final response = await httpGet(
|
||||
url: '${getMangaBaseUrl(source)}/search?query=${query.trim()}',
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
url: '${getMangaBaseUrl(source)}/search?query=${query.trim()}',
|
||||
source: source,
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
final rep = jsonDecode(response!);
|
||||
for (var ok in rep['suggestions']) {
|
||||
if (source == 'Read Comics Online') {
|
||||
|
|
@ -151,12 +160,15 @@ class Mmrcms extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
final dom = await httpGet(
|
||||
useUserAgent: true,
|
||||
url: chapter.url!,
|
||||
source: chapter.manga.value!.source!.toLowerCase(),
|
||||
resDom: true) as Document?;
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await await ref.watch(httpGetProvider(
|
||||
useUserAgent: true,
|
||||
url: chapter.url!,
|
||||
source: chapter.manga.value!.source!.toLowerCase(),
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!.querySelectorAll('#all > .img-responsive').isNotEmpty) {
|
||||
pageUrls = dom.querySelectorAll('#all > .img-responsive').map((e) {
|
||||
final RegExp regexx = RegExp(r'data-src="([^"]+)"');
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
|
||||
abstract class MangaYomiServices {
|
||||
|
|
@ -14,7 +15,7 @@ abstract class MangaYomiServices {
|
|||
String? description = "";
|
||||
List<Chapter> chapters = [];
|
||||
List<String> scanlators = [];
|
||||
List pageUrls = [];
|
||||
List<String> pageUrls = [];
|
||||
List<GetManga> mangaList = [];
|
||||
List<GetManga> mangaRes() {
|
||||
for (var i = 0; i < name.length; i++) {
|
||||
|
|
@ -62,14 +63,20 @@ abstract class MangaYomiServices {
|
|||
}
|
||||
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page});
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref});
|
||||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga, required String lang, required String source});
|
||||
Future<List<dynamic>?> getChapterUrl({
|
||||
required Chapter chapter,
|
||||
});
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref});
|
||||
Future<List<String>?> getChapterUrl(
|
||||
{required Chapter chapter, required AutoDisposeFutureProviderRef ref});
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query});
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref});
|
||||
}
|
||||
|
||||
class GetManga {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/sources/src/all/comick/src/model/chapter_page_comick.dart';
|
||||
import 'package:mangayomi/sources/src/all/comick/src/model/manga_chapter_detail.dart';
|
||||
|
|
@ -14,13 +15,16 @@ import 'package:mangayomi/sources/utils/utils.dart';
|
|||
class Comick extends MangaYomiServices {
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
source = source.toLowerCase();
|
||||
final response = await httpGet(
|
||||
url:
|
||||
'https://api.comick.fun/v1.0/search?sort=follow&page=$page&tachiyomi=true',
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'https://api.comick.fun/v1.0/search?sort=follow&page=$page&tachiyomi=true',
|
||||
source: source,
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
var popularManga = jsonDecode(response!) as List;
|
||||
|
||||
var popularMangaList =
|
||||
|
|
@ -37,11 +41,13 @@ class Comick extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
final response = await httpGet(
|
||||
url: 'https://api.comick.fun${manga.url}?tachiyomi=true',
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
url: 'https://api.comick.fun${manga.url}?tachiyomi=true',
|
||||
source: source,
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
var mangaDetail = jsonDecode(response!) as Map<String, dynamic>;
|
||||
|
||||
var mangaDetailLMap = MangaDetailModelComick.fromJson(mangaDetail);
|
||||
|
|
@ -59,15 +65,16 @@ class Comick extends MangaYomiServices {
|
|||
genre.add(regExp1.firstMatch(ok.toString())!.group(1)!);
|
||||
}
|
||||
description = mangaDetailLMap.comic!.desc;
|
||||
String tt = await findCurrentSlug(mangaDetailLMap.comic!.slug!);
|
||||
String tt = await findCurrentSlug(mangaDetailLMap.comic!.slug!, ref);
|
||||
String mangaId = tt.split('":"').last.replaceAll('"}', '');
|
||||
String limit = mangaDetailLMap.comic!.chapterCount.toString();
|
||||
|
||||
final responsee = await httpGet(
|
||||
url:
|
||||
'https://api.comick.fun/comic/$mangaId/chapters?lang=$lang&limit=$limit',
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
final responsee = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'https://api.comick.fun/comic/$mangaId/chapters?lang=$lang&limit=$limit',
|
||||
source: source,
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
var chapterDetail = jsonDecode(responsee!) as Map<String, dynamic>;
|
||||
var chapterDetailMap = MangaChapterModelComick.fromJson(chapterDetail);
|
||||
for (var chapter in chapterDetailMap.chapters!) {
|
||||
|
|
@ -89,12 +96,15 @@ class Comick extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
final response = await httpGet(
|
||||
url:
|
||||
'https://api.comick.fun/search?q=${query.trim()}&tachiyomi=true&page=1',
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'https://api.comick.fun/search?q=${query.trim()}&tachiyomi=true&page=1',
|
||||
source: source,
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
var popularManga = jsonDecode(response!) as List;
|
||||
var popularMangaList =
|
||||
popularManga.map((e) => MangaSearchModelComick.fromJson(e)).toList();
|
||||
|
|
@ -107,17 +117,20 @@ class Comick extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
String mangaId = chapter.url!.split('/').last.split('-').first;
|
||||
|
||||
final response = await httpGet(
|
||||
url: 'https://api.comick.fun/chapter/$mangaId?tachiyomi=true',
|
||||
source: 'comick',
|
||||
resDom: false) as String?;
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
url: 'https://api.comick.fun/chapter/$mangaId?tachiyomi=true',
|
||||
source: 'comick',
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
var data = jsonDecode(response!) as Map<String, dynamic>;
|
||||
var page = ChapterPageComick.fromJson(data);
|
||||
for (var url in page.chapter!.images!) {
|
||||
pageUrls.add(url.url);
|
||||
pageUrls.add(url.url!);
|
||||
}
|
||||
return pageUrls;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
|
|
@ -15,11 +16,11 @@ parseStatut(int i) {
|
|||
}
|
||||
}
|
||||
|
||||
Future findCurrentSlug(String oldSlug) async {
|
||||
Future findCurrentSlug(String oldSlug, AutoDisposeFutureProviderRef ref) async {
|
||||
var request = http.Request('GET',
|
||||
Uri.parse('https://api.comick.fun/tachiyomi/mapping?slugs=$oldSlug'));
|
||||
|
||||
request.headers.addAll(headers("comick"));
|
||||
request.headers.addAll(ref.watch(headersProvider(source: "comick")));
|
||||
|
||||
http.StreamedResponse response = await request.send();
|
||||
|
||||
|
|
@ -33,4 +34,3 @@ Future findCurrentSlug(String oldSlug) async {
|
|||
beautifyChapterName(String? vol, String? chap, String? title, String? lang) {
|
||||
return "${vol!.isNotEmpty ? chap!.isEmpty ? "Volume $vol " : "Vol. $vol " : ""}${chap!.isNotEmpty ? vol.isEmpty ? lang == "fr" ? "Chapitre $chap" : "Chapter $chap" : "Ch. $chap " : ""}${title!.isNotEmpty ? chap.isEmpty ? title : " : $title" : ""}";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter_js/flutter_js.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/services/http_service/http_service.dart';
|
||||
|
|
@ -12,11 +13,13 @@ class Mangahere extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
final dom = await httpGet(
|
||||
url: "http://www.mangahere.cc${manga.url}",
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url: "http://www.mangahere.cc${manga.url}",
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
' body > div > div > div.detail-info-right > p.detail-info-right-title > span.detail-info-right-title-tip')
|
||||
|
|
@ -107,11 +110,14 @@ class Mangahere extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
final dom = await httpGet(
|
||||
url: 'https://www.mangahere.cc/ranking/',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url: 'https://www.mangahere.cc/ranking/',
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
'body > div.container.weekrank.ranking > div > div > ul > li > a')
|
||||
|
|
@ -142,13 +148,16 @@ class Mangahere extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
final dom = await httpGet(
|
||||
url:
|
||||
'${getMangaBaseUrl(source)}/search?title=${query.trim()}&genres=&nogenres=&sort=&stype=1&name=&type=0&author_method=cw&author=&artist_method=cw&artist=&rating_method=eq&rating=&released_method=eq&released=&st=0',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'${getMangaBaseUrl(source)}/search?title=${query.trim()}&genres=&nogenres=&sort=&stype=1&name=&type=0&author_method=cw&author=&artist_method=cw&artist=&rating_method=eq&rating=&released_method=eq&released=&st=0',
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
|
|
@ -180,7 +189,9 @@ class Mangahere extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
JavascriptRuntime? flutterJs;
|
||||
flutterJs = getJavascriptRuntime();
|
||||
extractSecretKey(String response, JavascriptRuntime? flutterJs) {
|
||||
|
|
@ -203,8 +214,9 @@ class Mangahere extends MangaYomiServices {
|
|||
}
|
||||
|
||||
var link = "http://www.mangahere.cc${chapter.url!}";
|
||||
final response =
|
||||
await httpGet(url: link, source: "mangahere", resDom: false) as String?;
|
||||
final response = await ref.watch(
|
||||
httpGetProvider(url: link, source: "mangahere", resDom: false)
|
||||
.future) as String?;
|
||||
|
||||
dom.Document htmll = dom.Document.html(response!);
|
||||
int? pagesNumber = -1;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// ignore_for_file: depend_on_referenced_packages
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:html/dom.dart' as dom;
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
|
|
@ -15,9 +16,11 @@ class Japscan extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
final dom = await httpGet(url: manga.url!, source: source, resDom: true)
|
||||
as Document?;
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(
|
||||
httpGetProvider(url: manga.url!, source: source, resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!.querySelectorAll('.col-7 > p').isNotEmpty) {
|
||||
final images =
|
||||
dom.querySelectorAll('.col-5 ').map((e) => e.outerHtml).toList();
|
||||
|
|
@ -100,11 +103,12 @@ class Japscan extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
final dom = await httpGet(
|
||||
url: "https://www.japscan.lol/",
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = ref.watch(httpGetProvider(
|
||||
url: "https://www.japscan.lol/", source: source, resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!.querySelectorAll('#top_mangas_week > ul > li ').isNotEmpty) {
|
||||
final urls = dom
|
||||
.querySelectorAll('#top_mangas_week > ul > li > a')
|
||||
|
|
@ -128,11 +132,15 @@ class Japscan extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
final dom = await httpGet(
|
||||
url: "https://www.google.com/search?q=${query.toLowerCase()}+japscan",
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
"https://www.google.com/search?q=${query.toLowerCase()}+japscan",
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
|
||||
if (dom!.querySelectorAll("div > div > div > div > div > a").isNotEmpty) {
|
||||
final urls = dom
|
||||
|
|
@ -167,18 +175,21 @@ class Japscan extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
final response = await httpGet(
|
||||
useUserAgent: true,
|
||||
url: chapter.url!,
|
||||
source: "japscan",
|
||||
resDom: false) as String?;
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
useUserAgent: true,
|
||||
url: chapter.url!,
|
||||
source: "japscan",
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
RegExp regex = RegExp(r'<script src="/zjs/(.*?)"');
|
||||
Match? match = regex.firstMatch(response!);
|
||||
String zjsurl = match!.group(1)!;
|
||||
baseUrl = response;
|
||||
zjsUrl = "https://www.japscan.lol/zjs/$zjsurl";
|
||||
zjs();
|
||||
zjs(ref);
|
||||
await Future.doWhile(() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
if (isOk == true) {
|
||||
|
|
@ -192,9 +203,10 @@ class Japscan extends MangaYomiServices {
|
|||
bool isOk = false;
|
||||
String? baseUrl;
|
||||
String? zjsUrl;
|
||||
zjs() async {
|
||||
final html = await cloudflareBypassHtml(
|
||||
url: zjsUrl!, source: "japscan", useUserAgent: true);
|
||||
zjs(AutoDisposeFutureProviderRef ref) async {
|
||||
final html = await ref.watch(cloudflareBypassHtmlProvider(
|
||||
url: zjsUrl!, source: "japscan", useUserAgent: true)
|
||||
.future);
|
||||
dom.Document htmll = dom.Document.html(baseUrl!);
|
||||
final strings = html
|
||||
.replaceAll(RegExp(r'\\[(.*?)\\]'), '')
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/services/http_service/http_res_to_dom_html.dart';
|
||||
|
|
@ -10,11 +11,11 @@ class MangaKawaii extends MangaYomiServices {
|
|||
Future<GetManga?> getMangaDetail(
|
||||
{required GetManga manga,
|
||||
required String lang,
|
||||
required String source}) async {
|
||||
final dom = await httpGet(
|
||||
url: 'https://www.mangakawaii.io$url',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
required String source,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url: 'https://www.mangakawaii.io$url', source: source, resDom: true)
|
||||
.future) as Document?;
|
||||
List detail = [];
|
||||
manga.imageUrl =
|
||||
"https://cdn.mangakawaii.pics/uploads$url/cover/cover_250x350.jpg";
|
||||
|
|
@ -119,11 +120,12 @@ class MangaKawaii extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> getPopularManga(
|
||||
{required String source, required int page}) async {
|
||||
final dom = await httpGet(
|
||||
url: 'https://www.mangakawaii.io/',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url: 'https://www.mangakawaii.io/', source: source, resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!.querySelectorAll('a.hot-manga__item').isNotEmpty) {
|
||||
url = dom
|
||||
.querySelectorAll('a.hot-manga__item ')
|
||||
|
|
@ -143,12 +145,15 @@ class MangaKawaii extends MangaYomiServices {
|
|||
|
||||
@override
|
||||
Future<List<GetManga?>> searchManga(
|
||||
{required String source, required String query}) async {
|
||||
final dom = await httpGet(
|
||||
url:
|
||||
'https://www.mangakawaii.io/search?query=${query.trim()}&search_type=manga',
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
{required String source,
|
||||
required String query,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final dom = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'https://www.mangakawaii.io/search?query=${query.trim()}&search_type=manga',
|
||||
source: source,
|
||||
resDom: true)
|
||||
.future) as Document?;
|
||||
if (dom!
|
||||
.querySelectorAll(
|
||||
'#page-content > div > div > ul > li > div.section__list-group-right > div.section__list-group-header > div > h4 > a')
|
||||
|
|
@ -177,10 +182,13 @@ class MangaKawaii extends MangaYomiServices {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<dynamic>> getChapterUrl({required Chapter chapter}) async {
|
||||
final response =
|
||||
await httpGet(url: chapter.url!, source: "mangakawaii", resDom: false)
|
||||
as String?;
|
||||
Future<List<String>> getChapterUrl(
|
||||
{required Chapter chapter,
|
||||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final response = await ref.watch(
|
||||
httpGetProvider(url: chapter.url!, source: "mangakawaii", resDom: false)
|
||||
.future) as String?;
|
||||
|
||||
var chapterSlug = RegExp("""var chapter_slug = "([^"]*)";""")
|
||||
.allMatches(response!)
|
||||
.last
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
class HiveConstant {
|
||||
static String get hiveBoxManga => "manga_box_";
|
||||
static String get hiveBoxMangaInfo => "manga_box_info";
|
||||
static String get hiveBoxMangaSource => "manga_box_source";
|
||||
static String get hiveBoxAppSettings => "app_box_settings";
|
||||
static String get hiveBoxDownloads => "manga_box_downloads";
|
||||
static String get hiveBoxReaderMode => "readerMode_box_settings";
|
||||
}
|
||||
|
||||
const defaultUserAgent =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0";
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
|
||||
Map<String, String> headers(String source) {
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/services/http_service/cloudflare/providers/cookie_providers.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'headers.g.dart';
|
||||
|
||||
@riverpod
|
||||
Map<String, String> headers(HeadersRef ref, {String source = ""}) {
|
||||
source = source.toLowerCase();
|
||||
final cookie = Hive.box(HiveConstant.hiveBoxAppSettings)
|
||||
.get("$source-cookie", defaultValue: "");
|
||||
final userAgent = Hive.box(HiveConstant.hiveBoxAppSettings)
|
||||
.get("ua", defaultValue: defaultUserAgent);
|
||||
final cookie = ref.watch(cookieStateProvider(source));
|
||||
final userAgent = isar.settings.getSync(227)!.userAgent!;
|
||||
return source == 'mangakawaii'
|
||||
? {
|
||||
'Referer': 'https://www.mangakawaii.io/',
|
||||
|
|
|
|||
111
lib/utils/headers.g.dart
Normal file
111
lib/utils/headers.g.dart
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'headers.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$headersHash() => r'13a50be589fe0038aa6195027eb8da260d3b127f';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
typedef HeadersRef = AutoDisposeProviderRef<Map<String, String>>;
|
||||
|
||||
/// See also [headers].
|
||||
@ProviderFor(headers)
|
||||
const headersProvider = HeadersFamily();
|
||||
|
||||
/// See also [headers].
|
||||
class HeadersFamily extends Family<Map<String, String>> {
|
||||
/// See also [headers].
|
||||
const HeadersFamily();
|
||||
|
||||
/// See also [headers].
|
||||
HeadersProvider call({
|
||||
String source = "",
|
||||
}) {
|
||||
return HeadersProvider(
|
||||
source: source,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
HeadersProvider getProviderOverride(
|
||||
covariant HeadersProvider provider,
|
||||
) {
|
||||
return call(
|
||||
source: provider.source,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'headersProvider';
|
||||
}
|
||||
|
||||
/// See also [headers].
|
||||
class HeadersProvider extends AutoDisposeProvider<Map<String, String>> {
|
||||
/// See also [headers].
|
||||
HeadersProvider({
|
||||
this.source = "",
|
||||
}) : super.internal(
|
||||
(ref) => headers(
|
||||
ref,
|
||||
source: source,
|
||||
),
|
||||
from: headersProvider,
|
||||
name: r'headersProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$headersHash,
|
||||
dependencies: HeadersFamily._dependencies,
|
||||
allTransitiveDependencies: HeadersFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String source;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is HeadersProvider && other.source == source;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, source.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -3,8 +3,6 @@ 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/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/services/get_manga_detail.dart';
|
||||
import 'package:mangayomi/services/search_manga.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
|
|
@ -14,6 +12,7 @@ import 'package:mangayomi/utils/headers.dart';
|
|||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/views/library/search_text_form_field.dart';
|
||||
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/manga_image_card_widget.dart';
|
||||
|
||||
class GlobalSearchScreen extends ConsumerStatefulWidget {
|
||||
const GlobalSearchScreen({
|
||||
|
|
@ -84,8 +83,8 @@ class SourceSearchScreen extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final search =
|
||||
ref.watch(searchMangaProvider(source: source.sourceName!, query: query));
|
||||
final search = ref
|
||||
.watch(searchMangaProvider(source: source.sourceName!, query: query));
|
||||
return Scaffold(
|
||||
body: SizedBox(
|
||||
height: 240,
|
||||
|
|
@ -169,54 +168,14 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
|||
data: (data) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
final manga = Manga(
|
||||
imageUrl: data.imageUrl,
|
||||
name: data.name,
|
||||
genre: data.genre,
|
||||
author: data.author,
|
||||
status: data.status,
|
||||
description: data.description,
|
||||
link: data.url,
|
||||
source: data.source,
|
||||
lang: widget.lang,
|
||||
lastUpdate: DateTime.now().millisecondsSinceEpoch);
|
||||
|
||||
final empty = isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(widget.lang)
|
||||
.nameEqualTo(data.name)
|
||||
.sourceEqualTo(data.source)
|
||||
.isEmptySync();
|
||||
if (empty) {
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(manga);
|
||||
for (var i = 0; i < data.chapters.length; i++) {
|
||||
final chapters = Chapter(
|
||||
name: data.chapters[i].name,
|
||||
url: data.chapters[i].url,
|
||||
dateUpload: data.chapters[i].dateUpload,
|
||||
scanlator: data.chapters[i].scanlator,
|
||||
mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
isar.chapters.putSync(chapters);
|
||||
chapters.manga.saveSync();
|
||||
}
|
||||
});
|
||||
}
|
||||
final mangaId = isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(widget.lang)
|
||||
.nameEqualTo(data.name)
|
||||
.sourceEqualTo(data.source)
|
||||
.findFirstSync()!
|
||||
.id!;
|
||||
context.push('/manga-reader/detail', extra: mangaId);
|
||||
pushToMangaReaderDetail(
|
||||
context: context, getManga: data, lang: widget.lang);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 90,
|
||||
child: Column(children: [
|
||||
cachedNetworkImage(
|
||||
headers: headers(data.source!),
|
||||
headers: ref.watch(headersProvider(source: data.source!)),
|
||||
imageUrl: data.imageUrl!,
|
||||
width: 80,
|
||||
height: 120,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class SourcesScreen extends ConsumerWidget {
|
|||
.isAddedEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData ) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text("Empty"));
|
||||
}
|
||||
final entries = snapshot.data!;
|
||||
|
|
@ -66,7 +66,8 @@ class SourcesScreen extends ConsumerWidget {
|
|||
child: element.logoUrl!.isEmpty
|
||||
? const Icon(Icons.source_outlined)
|
||||
: CachedNetworkImage(
|
||||
httpHeaders: headers(element.sourceName!),
|
||||
httpHeaders: ref.watch(
|
||||
headersProvider(source: element.sourceName!)),
|
||||
imageUrl: element.logoUrl!,
|
||||
fit: BoxFit.contain,
|
||||
width: 37,
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> {
|
|||
data: (data) {
|
||||
final entries = data
|
||||
.where((element) => _textEditingController.text.isNotEmpty
|
||||
? element.chapter.value!.manga.value!.name!.toLowerCase()
|
||||
? element.chapter.value!.manga.value!.name!
|
||||
.toLowerCase()
|
||||
.contains(_textEditingController.text.toLowerCase())
|
||||
: true)
|
||||
.toList();
|
||||
|
|
@ -172,7 +173,8 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> {
|
|||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: cachedNetworkImage(
|
||||
headers: headers(manga.source!),
|
||||
headers: ref.watch(headersProvider(
|
||||
source: manga.source!)),
|
||||
imageUrl: manga.imageUrl!,
|
||||
width: 60,
|
||||
height: 90,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:mangayomi/main.dart';
|
|||
import 'package:mangayomi/models/category.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
|
|
@ -65,7 +66,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
|
||||
return Consumer(builder: (context, ref, child) {
|
||||
bool reverse =
|
||||
ref.watch(sortLibraryMangaStateProvider)["reverse"];
|
||||
ref.watch(sortLibraryMangaStateProvider).reverse!;
|
||||
|
||||
final continueReaderBtn = ref.watch(
|
||||
libraryShowContinueReadingButtonStateProvider);
|
||||
|
|
@ -94,9 +95,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
final bookmarkedFilterType = ref.watch(
|
||||
mangaFilterBookmarkedStateProvider(
|
||||
mangaList: _entries));
|
||||
final sortType =
|
||||
ref.watch(sortLibraryMangaStateProvider)['index']
|
||||
as int;
|
||||
final sortType = ref
|
||||
.watch(sortLibraryMangaStateProvider)
|
||||
.index as int;
|
||||
final numberOfItemsList = _filterAndSortMangas(
|
||||
data: man,
|
||||
downloadFilterType: downloadFilterType,
|
||||
|
|
@ -288,7 +289,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
}
|
||||
return Consumer(builder: (context, ref, child) {
|
||||
bool reverse =
|
||||
ref.watch(sortLibraryMangaStateProvider)["reverse"];
|
||||
ref.watch(sortLibraryMangaStateProvider).reverse!;
|
||||
final continueReaderBtn = ref
|
||||
.watch(libraryShowContinueReadingButtonStateProvider);
|
||||
final showNumbersOfItems =
|
||||
|
|
@ -312,15 +313,15 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
final bookmarkedFilterType = ref.watch(
|
||||
mangaFilterBookmarkedStateProvider(
|
||||
mangaList: _entries));
|
||||
final sortType = ref
|
||||
.watch(sortLibraryMangaStateProvider)['index'] as int;
|
||||
final sortType =
|
||||
ref.watch(sortLibraryMangaStateProvider).index;
|
||||
final numberOfItemsList = _filterAndSortMangas(
|
||||
data: man,
|
||||
downloadFilterType: downloadFilterType,
|
||||
unreadFilterType: unreadFilterType,
|
||||
startedFilterType: startedFilterType,
|
||||
bookmarkedFilterType: bookmarkedFilterType,
|
||||
sortType: sortType);
|
||||
sortType: sortType!);
|
||||
return Scaffold(
|
||||
appBar: _appBar(
|
||||
isNotFiltering,
|
||||
|
|
@ -494,7 +495,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
required bool continueReaderBtn,
|
||||
required int categoryId}) {
|
||||
final mangas = ref.watch(getAllMangaStreamProvider(categoryId: categoryId));
|
||||
final sortType = ref.watch(sortLibraryMangaStateProvider)['index'] as int;
|
||||
final sortType = ref.watch(sortLibraryMangaStateProvider).index;
|
||||
return mangas.when(
|
||||
data: (data) {
|
||||
final categoriNumberOfItemsList = _filterAndSortMangas(
|
||||
|
|
@ -503,7 +504,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
unreadFilterType: unreadFilterType,
|
||||
startedFilterType: startedFilterType,
|
||||
bookmarkedFilterType: bookmarkedFilterType,
|
||||
sortType: sortType);
|
||||
sortType: sortType!);
|
||||
return CircleAvatar(
|
||||
backgroundColor: Theme.of(context).focusColor,
|
||||
radius: 8,
|
||||
|
|
@ -537,7 +538,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
required WidgetRef ref,
|
||||
required DisplayType displayType}) {
|
||||
final mangas = ref.watch(getAllMangaStreamProvider(categoryId: categoryId));
|
||||
final sortType = ref.watch(sortLibraryMangaStateProvider)['index'] as int;
|
||||
final sortType = ref.watch(sortLibraryMangaStateProvider).index;
|
||||
final mangaIdsList = ref.watch(mangasListStateProvider);
|
||||
return Scaffold(
|
||||
body: mangas.when(
|
||||
|
|
@ -548,7 +549,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
unreadFilterType: unreadFilterType,
|
||||
startedFilterType: startedFilterType,
|
||||
bookmarkedFilterType: bookmarkedFilterType,
|
||||
sortType: sortType);
|
||||
sortType: sortType!);
|
||||
if (entries.isNotEmpty) {
|
||||
final entriesManga = reverse ? entries.reversed.toList() : entries;
|
||||
return displayType == DisplayType.list
|
||||
|
|
@ -594,7 +595,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
required DisplayType displayType,
|
||||
required WidgetRef ref,
|
||||
bool withouCategories = false}) {
|
||||
final sortType = ref.watch(sortLibraryMangaStateProvider)['index'] as int;
|
||||
final sortType = ref.watch(sortLibraryMangaStateProvider).index;
|
||||
final manga = withouCategories
|
||||
? ref.watch(getAllMangaWithoutCategoriesStreamProvider)
|
||||
: ref.watch(getAllMangaStreamProvider(categoryId: null));
|
||||
|
|
@ -607,7 +608,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
unreadFilterType: unreadFilterType,
|
||||
startedFilterType: startedFilterType,
|
||||
bookmarkedFilterType: bookmarkedFilterType,
|
||||
sortType: sortType);
|
||||
sortType: sortType!);
|
||||
if (entries.isNotEmpty) {
|
||||
final entriesManga = reverse ? entries.reversed.toList() : entries;
|
||||
return displayType == DisplayType.list
|
||||
|
|
@ -1021,7 +1022,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
DraggableMenu.open(
|
||||
context,
|
||||
DraggableMenu(
|
||||
ui: SoftModernDraggableMenu(barItem: Container()),
|
||||
ui: SoftModernDraggableMenu(barItem: Container(), radius: 20),
|
||||
expandable: true,
|
||||
expandedHeight: mediaHeight(context, 0.8),
|
||||
maxHeight: mediaHeight(context, 0.6),
|
||||
|
|
@ -1029,260 +1030,290 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
child: DefaultTabController(
|
||||
length: 3,
|
||||
child: Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
controller: tabBarController,
|
||||
tabs: const [
|
||||
Tab(text: "Filter"),
|
||||
Tab(text: "Sort"),
|
||||
Tab(text: "Display"),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child:
|
||||
TabBarView(controller: tabBarController, children: [
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
return Column(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Theme.of(context).scaffoldBackgroundColor),
|
||||
child: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
controller: tabBarController,
|
||||
tabs: const [
|
||||
Tab(text: "Filter"),
|
||||
Tab(text: "Sort"),
|
||||
Tab(text: "Display"),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: TabBarView(
|
||||
controller: tabBarController,
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Downloaded",
|
||||
type: ref.watch(
|
||||
mangaFilterDownloadedStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
return Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Downloaded",
|
||||
type: ref.watch(
|
||||
mangaFilterDownloadedStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Unread",
|
||||
type: ref.watch(
|
||||
mangaFilterUnreadStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(mangaFilterUnreadStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Started",
|
||||
type: ref.watch(
|
||||
mangaFilterStartedStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(mangaFilterStartedStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Bookmarked",
|
||||
type: ref.watch(
|
||||
mangaFilterBookmarkedStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
ref
|
||||
.read(
|
||||
mangaFilterBookmarkedStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
});
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
final reverse = ref
|
||||
.read(sortLibraryMangaStateProvider.notifier)
|
||||
.isReverse();
|
||||
final reverseChapter =
|
||||
ref.watch(sortLibraryMangaStateProvider);
|
||||
return Column(
|
||||
children: [
|
||||
for (var i = 0; i < 7; i++)
|
||||
ListTileChapterSort(
|
||||
label: _getSortNameByIndex(i),
|
||||
reverse: reverse,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(sortLibraryMangaStateProvider
|
||||
.notifier)
|
||||
.set(i);
|
||||
},
|
||||
showLeading: reverseChapter['index'] == i,
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
final display =
|
||||
ref.watch(libraryDisplayTypeStateProvider);
|
||||
final displayV = ref
|
||||
.read(libraryDisplayTypeStateProvider.notifier);
|
||||
final showCategoryTabs =
|
||||
ref.watch(libraryShowCategoryTabsStateProvider);
|
||||
final continueReaderBtn = ref.watch(
|
||||
libraryShowContinueReadingButtonStateProvider);
|
||||
final showNumbersOfItems = ref
|
||||
.watch(libraryShowNumbersOfItemsStateProvider);
|
||||
final downloadedChapter = ref
|
||||
.watch(libraryDownloadedChaptersStateProvider);
|
||||
final language =
|
||||
ref.watch(libraryLanguageStateProvider);
|
||||
return SingleChildScrollView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Display mode"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: DisplayType.values
|
||||
.map(
|
||||
(e) => RadioListTile<DisplayType>(
|
||||
title: Text(
|
||||
displayV
|
||||
.getLibraryDisplayTypeName(
|
||||
e.name),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
fontSize: 14),
|
||||
),
|
||||
value: e,
|
||||
groupValue: displayV
|
||||
.getLibraryDisplayTypeValue(
|
||||
display),
|
||||
selected: true,
|
||||
onChanged: (value) {
|
||||
displayV.setLibraryDisplayType(
|
||||
value!);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList()),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Badges"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 10, top: 5),
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
mangaFilterDownloadedStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Unread",
|
||||
type: ref.watch(
|
||||
mangaFilterUnreadStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
mangaFilterUnreadStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Started",
|
||||
type: ref.watch(
|
||||
mangaFilterStartedStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
mangaFilterStartedStateProvider(
|
||||
mangaList: _entries)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Bookmarked",
|
||||
type: ref.watch(
|
||||
mangaFilterBookmarkedStateProvider(
|
||||
mangaList: _entries)),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
ref
|
||||
.read(
|
||||
mangaFilterBookmarkedStateProvider(
|
||||
mangaList:
|
||||
_entries)
|
||||
.notifier)
|
||||
.update();
|
||||
});
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
final reverse = ref
|
||||
.read(sortLibraryMangaStateProvider
|
||||
.notifier)
|
||||
.isReverse();
|
||||
final reverseChapter =
|
||||
ref.watch(sortLibraryMangaStateProvider);
|
||||
return Column(
|
||||
children: [
|
||||
for (var i = 0; i < 7; i++)
|
||||
ListTileChapterSort(
|
||||
label: _getSortNameByIndex(i),
|
||||
reverse: reverse,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
sortLibraryMangaStateProvider
|
||||
.notifier)
|
||||
.set(i);
|
||||
},
|
||||
showLeading:
|
||||
reverseChapter.index == i,
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
final display = ref
|
||||
.watch(libraryDisplayTypeStateProvider);
|
||||
final displayV = ref.read(
|
||||
libraryDisplayTypeStateProvider.notifier);
|
||||
final showCategoryTabs = ref.watch(
|
||||
libraryShowCategoryTabsStateProvider);
|
||||
final continueReaderBtn = ref.watch(
|
||||
libraryShowContinueReadingButtonStateProvider);
|
||||
final showNumbersOfItems = ref.watch(
|
||||
libraryShowNumbersOfItemsStateProvider);
|
||||
final downloadedChapter = ref.watch(
|
||||
libraryDownloadedChaptersStateProvider);
|
||||
final language =
|
||||
ref.watch(libraryLanguageStateProvider);
|
||||
return SingleChildScrollView(
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Downloaded chapters",
|
||||
type: downloadedChapter ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryDownloadedChaptersStateProvider
|
||||
.notifier)
|
||||
.set(!downloadedChapter);
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Language",
|
||||
type: language ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryLanguageStateProvider
|
||||
.notifier)
|
||||
.set(!language);
|
||||
}),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Display mode"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: DisplayType.values
|
||||
.map(
|
||||
(e) => RadioListTile<
|
||||
DisplayType>(
|
||||
title: Text(
|
||||
displayV
|
||||
.getLibraryDisplayTypeName(
|
||||
e.name),
|
||||
style: TextStyle(
|
||||
color:
|
||||
Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
fontSize: 14),
|
||||
),
|
||||
value: e,
|
||||
groupValue: displayV
|
||||
.getLibraryDisplayTypeValue(
|
||||
display),
|
||||
selected: true,
|
||||
onChanged: (value) {
|
||||
displayV
|
||||
.setLibraryDisplayType(
|
||||
value!);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList()),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Badges"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 10, top: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Downloaded chapters",
|
||||
type:
|
||||
downloadedChapter ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryDownloadedChaptersStateProvider
|
||||
.notifier)
|
||||
.set(
|
||||
!downloadedChapter);
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Language",
|
||||
type: language ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryLanguageStateProvider
|
||||
.notifier)
|
||||
.set(!language);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Tabs"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 10, top: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Show category tabs",
|
||||
type:
|
||||
showCategoryTabs ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryShowCategoryTabsStateProvider
|
||||
.notifier)
|
||||
.set(!showCategoryTabs);
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label:
|
||||
"Show numbers of items",
|
||||
type: showNumbersOfItems
|
||||
? 1
|
||||
: 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryShowNumbersOfItemsStateProvider
|
||||
.notifier)
|
||||
.set(
|
||||
!showNumbersOfItems);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Others"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 10, top: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label:
|
||||
"Show continue reading button",
|
||||
type:
|
||||
continueReaderBtn ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryShowContinueReadingButtonStateProvider
|
||||
.notifier)
|
||||
.set(
|
||||
!continueReaderBtn);
|
||||
}),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Tabs"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 10, top: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Show category tabs",
|
||||
type: showCategoryTabs ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryShowCategoryTabsStateProvider
|
||||
.notifier)
|
||||
.set(!showCategoryTabs);
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Show numbers of items",
|
||||
type: showNumbersOfItems ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryShowNumbersOfItemsStateProvider
|
||||
.notifier)
|
||||
.set(!showNumbersOfItems);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 20, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Others"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 10, top: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label:
|
||||
"Show continue reading button",
|
||||
type: continueReaderBtn ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
libraryShowContinueReadingButtonStateProvider
|
||||
.notifier)
|
||||
.set(!continueReaderBtn);
|
||||
}),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
))));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'library_state_provider.g.dart';
|
||||
|
||||
|
|
@ -9,9 +9,7 @@ part 'library_state_provider.g.dart';
|
|||
class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
||||
@override
|
||||
String build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('displayType', defaultValue: DisplayType.coverOnlyGrid.name)!;
|
||||
return isar.settings.getSync(227)!.displayType.name;
|
||||
}
|
||||
|
||||
DisplayType getLibraryDisplayTypeValue(String value) {
|
||||
|
|
@ -35,18 +33,14 @@ class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
|||
}
|
||||
|
||||
void setLibraryDisplayType(DisplayType displayType) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = displayType.name;
|
||||
ref.watch(hiveBoxSettingsProvider).put('displayType', displayType.name);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..displayType = displayType);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
enum DisplayType {
|
||||
compactGrid,
|
||||
comfortableGrid,
|
||||
coverOnlyGrid,
|
||||
list,
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
||||
@override
|
||||
|
|
@ -56,13 +50,14 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("filterMangasDownload", defaultValue: 0);
|
||||
return isar.settings.getSync(227)!.libraryFilterMangasDownloadType!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref.watch(hiveBoxSettingsProvider).put("filterMangasDownload", type);
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryFilterMangasDownloadType = type);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
@ -86,13 +81,14 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("filterMangasUnread", defaultValue: 0);
|
||||
return isar.settings.getSync(227)!.libraryFilterMangasUnreadType!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref.watch(hiveBoxSettingsProvider).put("filterMangasUnread", type);
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryFilterMangasUnreadType = type);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
@ -165,13 +161,14 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("filterMangasStarted", defaultValue: 0);
|
||||
return isar.settings.getSync(227)!.libraryFilterMangasStartedType!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref.watch(hiveBoxSettingsProvider).put("filterMangasStarted", type);
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryFilterMangasStartedType = type);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
@ -244,13 +241,14 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("filterMangasBookMarked", defaultValue: 0);
|
||||
return isar.settings.getSync(227)!.libraryFilterMangasBookMarkedType!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref.watch(hiveBoxSettingsProvider).put("filterMangasBookMarked", type);
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryFilterMangasBookMarkedType = type);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
@ -337,14 +335,15 @@ class MangasFilterResultState extends _$MangasFilterResultState {
|
|||
class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('libraryShowCategoryTabs', defaultValue: false)!;
|
||||
return isar.settings.getSync(227)!.libraryShowCategoryTabs!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = value;
|
||||
ref.watch(hiveBoxSettingsProvider).put('libraryShowCategoryTabs', value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryShowCategoryTabs = value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -352,14 +351,15 @@ class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
|||
class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('libraryDownloadedChapters', defaultValue: false)!;
|
||||
return isar.settings.getSync(227)!.libraryDownloadedChapters!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = value;
|
||||
ref.watch(hiveBoxSettingsProvider).put('libraryDownloadedChapters', value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryDownloadedChapters = value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -367,14 +367,15 @@ class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
|||
class LibraryLanguageState extends _$LibraryLanguageState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('libraryLanguage', defaultValue: false)!;
|
||||
return isar.settings.getSync(227)!.libraryShowLanguage!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = value;
|
||||
ref.watch(hiveBoxSettingsProvider).put('libraryLanguage', value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryShowLanguage = value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -382,14 +383,15 @@ class LibraryLanguageState extends _$LibraryLanguageState {
|
|||
class LibraryShowNumbersOfItemsState extends _$LibraryShowNumbersOfItemsState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('libraryShowNumbersOfItems', defaultValue: false)!;
|
||||
return isar.settings.getSync(227)!.libraryShowNumbersOfItems!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = value;
|
||||
ref.watch(hiveBoxSettingsProvider).put('libraryShowNumbersOfItems', value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryShowNumbersOfItems = value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,33 +400,34 @@ class LibraryShowContinueReadingButtonState
|
|||
extends _$LibraryShowContinueReadingButtonState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('libraryShowContinueReadingButton', defaultValue: false)!;
|
||||
return isar.settings.getSync(227)!.libraryShowContinueReadingButton!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = value;
|
||||
ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.put('libraryShowContinueReadingButton', value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..libraryShowContinueReadingButton = value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class SortLibraryMangaState extends _$SortLibraryMangaState {
|
||||
@override
|
||||
dynamic build() {
|
||||
return ref.watch(hiveBoxSettingsProvider).get("sortLibraryMangaMap",
|
||||
defaultValue: {"reverse": false, "index": 2});
|
||||
SortLibraryManga build() {
|
||||
return isar.settings.getSync(227)!.sortLibraryManga!;
|
||||
}
|
||||
|
||||
void update(bool reverse, int index) {
|
||||
var value = {
|
||||
"reverse": state['index'] == index ? !reverse : reverse,
|
||||
"index": index
|
||||
};
|
||||
ref.watch(hiveBoxSettingsProvider).put("sortLibraryMangaMap", value);
|
||||
var value = SortLibraryManga()
|
||||
..index = index
|
||||
..reverse = state.index == index ? !reverse : reverse;
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
isar.settings.putSync(settings..sortLibraryManga = value);
|
||||
});
|
||||
state = value;
|
||||
}
|
||||
|
||||
|
|
@ -434,7 +437,7 @@ class SortLibraryMangaState extends _$SortLibraryMangaState {
|
|||
}
|
||||
|
||||
bool isReverse() {
|
||||
return state["reverse"];
|
||||
return state.reverse!;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ part of 'library_state_provider.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$libraryDisplayTypeStateHash() =>
|
||||
r'746bd6dac3600802c3ab5751b3c1def881274b3a';
|
||||
r'7686533c6ece9f6aa5fbcbc70854ffeae16c33f8';
|
||||
|
||||
/// See also [LibraryDisplayTypeState].
|
||||
@ProviderFor(LibraryDisplayTypeState)
|
||||
|
|
@ -24,7 +24,7 @@ final libraryDisplayTypeStateProvider =
|
|||
|
||||
typedef _$LibraryDisplayTypeState = AutoDisposeNotifier<String>;
|
||||
String _$mangaFilterDownloadedStateHash() =>
|
||||
r'96066910b5ff9ca0efcfef7c1411b18e94b7b250';
|
||||
r'35ddc6b776881939f168fc0ef78abdd7c954e56b';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -144,7 +144,7 @@ class MangaFilterDownloadedStateProvider
|
|||
}
|
||||
|
||||
String _$mangaFilterUnreadStateHash() =>
|
||||
r'c6ae52956f7889ee70a640230993dc7b76f4e2f2';
|
||||
r'53aef2b3df212d16f4798392245af418f211c8a2';
|
||||
|
||||
abstract class _$MangaFilterUnreadState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -243,7 +243,7 @@ class MangaFilterUnreadStateProvider
|
|||
}
|
||||
|
||||
String _$mangaFilterStartedStateHash() =>
|
||||
r'4adef7169a977bdc582ae38c7fd453f42775bcef';
|
||||
r'15282a1a4ea9682b287adbd37ee9c62b439af457';
|
||||
|
||||
abstract class _$MangaFilterStartedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -342,7 +342,7 @@ class MangaFilterStartedStateProvider
|
|||
}
|
||||
|
||||
String _$mangaFilterBookmarkedStateHash() =>
|
||||
r'8379126605e9c4b05b52f254dd0d3d6a492b526c';
|
||||
r'ab2c1228590fd320935db757559f1436f296ec5f';
|
||||
|
||||
abstract class _$MangaFilterBookmarkedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -540,7 +540,7 @@ class MangasFilterResultStateProvider
|
|||
}
|
||||
|
||||
String _$libraryShowCategoryTabsStateHash() =>
|
||||
r'0ee90372d42a11638479aadcf8ea5e688bb48369';
|
||||
r'58e5cd32e60902033a76935b0c710ba56a14e224';
|
||||
|
||||
/// See also [LibraryShowCategoryTabsState].
|
||||
@ProviderFor(LibraryShowCategoryTabsState)
|
||||
|
|
@ -557,7 +557,7 @@ final libraryShowCategoryTabsStateProvider =
|
|||
|
||||
typedef _$LibraryShowCategoryTabsState = AutoDisposeNotifier<bool>;
|
||||
String _$libraryDownloadedChaptersStateHash() =>
|
||||
r'bdbb37edcd547e8f34df39d9221bb85051f765ae';
|
||||
r'd79136babd57bf5b98609f1c21b9da046a0b884c';
|
||||
|
||||
/// See also [LibraryDownloadedChaptersState].
|
||||
@ProviderFor(LibraryDownloadedChaptersState)
|
||||
|
|
@ -574,7 +574,7 @@ final libraryDownloadedChaptersStateProvider =
|
|||
|
||||
typedef _$LibraryDownloadedChaptersState = AutoDisposeNotifier<bool>;
|
||||
String _$libraryLanguageStateHash() =>
|
||||
r'b454724faeda5de41a67952cf9a80366fb72be9c';
|
||||
r'fd83c5473d90b1ad43dc5182d9b739a6ed9202de';
|
||||
|
||||
/// See also [LibraryLanguageState].
|
||||
@ProviderFor(LibraryLanguageState)
|
||||
|
|
@ -591,7 +591,7 @@ final libraryLanguageStateProvider =
|
|||
|
||||
typedef _$LibraryLanguageState = AutoDisposeNotifier<bool>;
|
||||
String _$libraryShowNumbersOfItemsStateHash() =>
|
||||
r'f6eeb5df01cee601f05e442229830f64891a5fe9';
|
||||
r'ea02157581d2b08c944d692f0bb9154e843dd1f1';
|
||||
|
||||
/// See also [LibraryShowNumbersOfItemsState].
|
||||
@ProviderFor(LibraryShowNumbersOfItemsState)
|
||||
|
|
@ -608,7 +608,7 @@ final libraryShowNumbersOfItemsStateProvider =
|
|||
|
||||
typedef _$LibraryShowNumbersOfItemsState = AutoDisposeNotifier<bool>;
|
||||
String _$libraryShowContinueReadingButtonStateHash() =>
|
||||
r'4d5553dc605e87714b3c23f54c52c1911910a8aa';
|
||||
r'5e51fc2e1d8b098018abead4790c180256ab08a6';
|
||||
|
||||
/// See also [LibraryShowContinueReadingButtonState].
|
||||
@ProviderFor(LibraryShowContinueReadingButtonState)
|
||||
|
|
@ -626,12 +626,12 @@ final libraryShowContinueReadingButtonStateProvider =
|
|||
|
||||
typedef _$LibraryShowContinueReadingButtonState = AutoDisposeNotifier<bool>;
|
||||
String _$sortLibraryMangaStateHash() =>
|
||||
r'81abfe6c2841cf7b25301928d88f8af80cd480fd';
|
||||
r'0f23a413f94e254d2ba03166ab941e4d4eb67b41';
|
||||
|
||||
/// See also [SortLibraryMangaState].
|
||||
@ProviderFor(SortLibraryMangaState)
|
||||
final sortLibraryMangaStateProvider =
|
||||
AutoDisposeNotifierProvider<SortLibraryMangaState, dynamic>.internal(
|
||||
final sortLibraryMangaStateProvider = AutoDisposeNotifierProvider<
|
||||
SortLibraryMangaState, SortLibraryManga>.internal(
|
||||
SortLibraryMangaState.new,
|
||||
name: r'sortLibraryMangaStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
|
|
@ -641,7 +641,7 @@ final sortLibraryMangaStateProvider =
|
|||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$SortLibraryMangaState = AutoDisposeNotifier<dynamic>;
|
||||
typedef _$SortLibraryMangaState = AutoDisposeNotifier<SortLibraryManga>;
|
||||
String _$mangasListStateHash() => r'ad1cc419dfd3793bfc8c90f3ce8b7726561dd9ad';
|
||||
|
||||
/// See also [MangasListState].
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
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/download.dart';
|
||||
|
|
@ -16,6 +15,7 @@ import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
|||
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/error_text.dart';
|
||||
import 'package:mangayomi/views/widgets/gridview_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/manga_image_card_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/progress_center.dart';
|
||||
|
||||
class LibraryGridViewWidget extends StatelessWidget {
|
||||
|
|
@ -62,8 +62,10 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
.read(mangasListStateProvider.notifier)
|
||||
.update(entriesManga[index]);
|
||||
} else {
|
||||
context.push('/manga-reader/detail',
|
||||
extra: entriesManga[index].id);
|
||||
pushToMangaReaderDetail(
|
||||
context: context,
|
||||
lang: entriesManga[index].lang!,
|
||||
mangaM: entriesManga[index]);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
|
|
@ -91,7 +93,8 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
Stack(
|
||||
children: [
|
||||
cachedNetworkImage(
|
||||
headers: headers(entriesManga[index].source!),
|
||||
headers: ref.watch(headersProvider(
|
||||
source: entriesManga[index].source!)),
|
||||
imageUrl: entriesManga[index].imageUrl!,
|
||||
width: 200,
|
||||
height: 270,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
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/download.dart';
|
||||
|
|
@ -14,6 +13,7 @@ import 'package:mangayomi/utils/headers.dart';
|
|||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/error_text.dart';
|
||||
import 'package:mangayomi/views/widgets/listview_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/manga_image_card_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/progress_center.dart';
|
||||
|
||||
class LibraryListViewWidget extends StatelessWidget {
|
||||
|
|
@ -52,8 +52,10 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
.read(mangasListStateProvider.notifier)
|
||||
.update(entriesManga[index]);
|
||||
} else {
|
||||
context.push('/manga-reader/detail',
|
||||
extra: entriesManga[index].id);
|
||||
pushToMangaReaderDetail(
|
||||
context: context,
|
||||
lang: entriesManga[index].lang!,
|
||||
mangaM: entriesManga[index]);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
|
|
@ -88,7 +90,8 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
topLeft: Radius.circular(5),
|
||||
bottomLeft: Radius.circular(5)),
|
||||
child: cachedNetworkImage(
|
||||
headers: headers(entriesManga[index].source!),
|
||||
headers: ref.watch(headersProvider(
|
||||
source: entriesManga[index].source!)),
|
||||
imageUrl: entriesManga[index].imageUrl!,
|
||||
width: 40,
|
||||
height: 40,
|
||||
|
|
|
|||
|
|
@ -64,16 +64,17 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final chapterNameList = ref.watch(chaptersListStateProvider);
|
||||
bool reverse = ref
|
||||
.watch(sortChapterStateProvider(mangaId: widget.manga!.id!))["reverse"];
|
||||
.watch(sortChapterStateProvider(mangaId: widget.manga!.id!))
|
||||
.reverse!;
|
||||
final filterUnread =
|
||||
ref.watch(chapterFilterUnreadStateProvider(mangaId: widget.manga!.id!));
|
||||
final filterBookmarked = ref.watch(
|
||||
chapterFilterBookmarkedStateProvider(mangaId: widget.manga!.id!));
|
||||
final filterDownloaded = ref.watch(
|
||||
chapterFilterDownloadedStateProvider(mangaId: widget.manga!.id!));
|
||||
final sortChapter =
|
||||
ref.watch(sortChapterStateProvider(mangaId: widget.manga!.id!))['index']
|
||||
as int;
|
||||
final sortChapter = ref
|
||||
.watch(sortChapterStateProvider(mangaId: widget.manga!.id!))
|
||||
.index as int;
|
||||
final chapters =
|
||||
ref.watch(getChaptersStreamProvider(mangaId: widget.manga!.id!));
|
||||
return NotificationListener<UserScrollNotification>(
|
||||
|
|
@ -180,7 +181,8 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
? Stack(
|
||||
children: [
|
||||
cachedNetworkImage(
|
||||
headers: headers(widget.manga!.source!),
|
||||
headers: ref.watch(
|
||||
headersProvider(source: widget.manga!.source!)),
|
||||
imageUrl: widget.manga!.imageUrl!,
|
||||
width: mediaWidth(context, 1),
|
||||
height: 410,
|
||||
|
|
@ -568,7 +570,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
DraggableMenu.open(
|
||||
context,
|
||||
DraggableMenu(
|
||||
ui: ClassicDraggableMenu(barItem: Container()),
|
||||
ui: ClassicDraggableMenu(barItem: Container(), radius: 20),
|
||||
expandable: false,
|
||||
maxHeight: 240,
|
||||
fastDrag: false,
|
||||
|
|
@ -576,114 +578,121 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
child: DefaultTabController(
|
||||
length: 3,
|
||||
child: Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
controller: tabBarController,
|
||||
tabs: const [
|
||||
Tab(text: "Filter"),
|
||||
Tab(text: "Sort"),
|
||||
Tab(text: "Display"),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: TabBarView(controller: tabBarController, children: [
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
return Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Downloaded",
|
||||
type: ref.watch(
|
||||
chapterFilterDownloadedStateProvider(
|
||||
mangaId: widget.manga!.id!)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
chapterFilterDownloadedStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Unread",
|
||||
type: ref.watch(
|
||||
chapterFilterUnreadStateProvider(
|
||||
mangaId: widget.manga!.id!)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(chapterFilterUnreadStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Bookmarked",
|
||||
type: ref.watch(
|
||||
chapterFilterBookmarkedStateProvider(
|
||||
mangaId: widget.manga!.id!)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
chapterFilterBookmarkedStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
final reverse = ref
|
||||
.read(sortChapterStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.isReverse();
|
||||
final reverseChapter = ref.watch(
|
||||
sortChapterStateProvider(
|
||||
mangaId: widget.manga!.id!));
|
||||
return Column(
|
||||
children: [
|
||||
for (var i = 0; i < 3; i++)
|
||||
ListTileChapterSort(
|
||||
label: _getSortNameByIndex(i),
|
||||
reverse: reverse,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(sortChapterStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.set(i);
|
||||
},
|
||||
showLeading: reverseChapter['index'] == i,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Theme.of(context).scaffoldBackgroundColor),
|
||||
child: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
controller: tabBarController,
|
||||
tabs: const [
|
||||
Tab(text: "Filter"),
|
||||
Tab(text: "Sort"),
|
||||
Tab(text: "Display"),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child:
|
||||
TabBarView(controller: tabBarController, children: [
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
return Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: "Downloaded",
|
||||
type: ref.watch(
|
||||
chapterFilterDownloadedStateProvider(
|
||||
mangaId: widget.manga!.id!)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
chapterFilterDownloadedStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Unread",
|
||||
type: ref.watch(
|
||||
chapterFilterUnreadStateProvider(
|
||||
mangaId: widget.manga!.id!)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(chapterFilterUnreadStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: "Bookmarked",
|
||||
type: ref.watch(
|
||||
chapterFilterBookmarkedStateProvider(
|
||||
mangaId: widget.manga!.id!)),
|
||||
onTap: () {
|
||||
ref
|
||||
.read(
|
||||
chapterFilterBookmarkedStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.update();
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
final reverse = ref
|
||||
.read(sortChapterStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.isReverse();
|
||||
final reverseChapter = ref.watch(
|
||||
sortChapterStateProvider(
|
||||
mangaId: widget.manga!.id!));
|
||||
return Column(
|
||||
children: [
|
||||
for (var i = 0; i < 3; i++)
|
||||
ListTileChapterSort(
|
||||
label: _getSortNameByIndex(i),
|
||||
reverse: reverse,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(sortChapterStateProvider(
|
||||
mangaId: widget.manga!.id!)
|
||||
.notifier)
|
||||
.set(i);
|
||||
},
|
||||
showLeading: reverseChapter.index == i,
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
return Column(
|
||||
children: [
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
title: const Text("Source title"),
|
||||
value: "e",
|
||||
groupValue: "e",
|
||||
selected: true,
|
||||
onChanged: (value) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Consumer(builder: (context, ref, chil) {
|
||||
return Column(
|
||||
children: [
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
title: const Text("Source title"),
|
||||
value: "e",
|
||||
groupValue: "e",
|
||||
selected: true,
|
||||
onChanged: (value) {},
|
||||
),
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
title: const Text("Chapter number"),
|
||||
value: "ej",
|
||||
groupValue: "e",
|
||||
selected: false,
|
||||
onChanged: (value) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
title: const Text("Chapter number"),
|
||||
value: "ej",
|
||||
groupValue: "e",
|
||||
selected: false,
|
||||
onChanged: (value) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
|
@ -706,7 +715,8 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
Positioned(
|
||||
top: 0,
|
||||
child: cachedNetworkImage(
|
||||
headers: headers(widget.manga!.source!),
|
||||
headers:
|
||||
ref.watch(headersProvider(source: widget.manga!.source!)),
|
||||
imageUrl: widget.manga!.imageUrl!,
|
||||
width: mediaWidth(context, 1),
|
||||
height: 250,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import 'package:mangayomi/main.dart';
|
|||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/views/manga/download/providers/download_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'state_providers.g.dart';
|
||||
|
|
@ -79,17 +79,32 @@ class IsExtendedState extends _$IsExtendedState {
|
|||
@riverpod
|
||||
class SortChapterState extends _$SortChapterState {
|
||||
@override
|
||||
dynamic build({required int mangaId}) {
|
||||
return ref.watch(hiveBoxSettingsProvider).get("$mangaId-sortChapterMap",
|
||||
defaultValue: {"reverse": false, "index": 2});
|
||||
SortChapter build({required int mangaId}) {
|
||||
return isar.settings
|
||||
.getSync(227)!
|
||||
.sortChapterList!
|
||||
.where((element) => element.mangaId == mangaId)
|
||||
.toList()
|
||||
.first;
|
||||
}
|
||||
|
||||
void update(bool reverse, int index) {
|
||||
var value = {
|
||||
"reverse": state['index'] == index ? !reverse : reverse,
|
||||
"index": index
|
||||
};
|
||||
ref.watch(hiveBoxSettingsProvider).put("$mangaId-sortChapterMap", value);
|
||||
var value = SortChapter()
|
||||
..index = index
|
||||
..mangaId = mangaId
|
||||
..reverse = state.index == index ? !reverse : reverse;
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
List<SortChapter>? sortChapterList = [];
|
||||
for (var sortChapter in settings.sortChapterList!) {
|
||||
if (sortChapter.mangaId != mangaId) {
|
||||
sortChapterList.add(sortChapter);
|
||||
}
|
||||
}
|
||||
sortChapterList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..sortChapterList = sortChapterList);
|
||||
});
|
||||
|
||||
state = value;
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +114,7 @@ class SortChapterState extends _$SortChapterState {
|
|||
}
|
||||
|
||||
bool isReverse() {
|
||||
return state["reverse"];
|
||||
return state.reverse!;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,15 +127,32 @@ class ChapterFilterDownloadedState extends _$ChapterFilterDownloadedState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("$mangaId-filterChapterDownload", defaultValue: 0);
|
||||
return isar.settings
|
||||
.getSync(227)!
|
||||
.chapterFilterDownloadedList!
|
||||
.where((element) => element.mangaId == mangaId)
|
||||
.toList()
|
||||
.first
|
||||
.type!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.put("$mangaId-filterChapterDownload", type);
|
||||
var value = ChapterFilterDownloaded()
|
||||
..type = type
|
||||
..mangaId = mangaId;
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
List<ChapterFilterDownloaded>? chapterFilterDownloadedList = [];
|
||||
for (var filterChapter in settings.chapterFilterDownloadedList!) {
|
||||
if (filterChapter.mangaId != mangaId) {
|
||||
chapterFilterDownloadedList.add(filterChapter);
|
||||
}
|
||||
}
|
||||
chapterFilterDownloadedList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(
|
||||
settings..chapterFilterDownloadedList = chapterFilterDownloadedList);
|
||||
});
|
||||
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
@ -144,15 +176,31 @@ class ChapterFilterUnreadState extends _$ChapterFilterUnreadState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("$mangaId-filterChapterUnread", defaultValue: 0);
|
||||
return isar.settings
|
||||
.getSync(227)!
|
||||
.chapterFilterUnreadList!
|
||||
.where((element) => element.mangaId == mangaId)
|
||||
.toList()
|
||||
.first
|
||||
.type!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.put("$mangaId-filterChapterUnread", type);
|
||||
var value = ChapterFilterUnread()
|
||||
..type = type
|
||||
..mangaId = mangaId;
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
List<ChapterFilterUnread>? chapterFilterUnreadList = [];
|
||||
for (var filterChapter in settings.chapterFilterUnreadList!) {
|
||||
if (filterChapter.mangaId != mangaId) {
|
||||
chapterFilterUnreadList.add(filterChapter);
|
||||
}
|
||||
}
|
||||
chapterFilterUnreadList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings
|
||||
.putSync(settings..chapterFilterUnreadList = chapterFilterUnreadList);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
@ -176,15 +224,31 @@ class ChapterFilterBookmarkedState extends _$ChapterFilterBookmarkedState {
|
|||
}
|
||||
|
||||
int getType() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get("$mangaId-filterChapterBookMark", defaultValue: 0);
|
||||
return isar.settings
|
||||
.getSync(227)!
|
||||
.chapterFilterBookmarkedList!
|
||||
.where((element) => element.mangaId == mangaId)
|
||||
.toList()
|
||||
.first
|
||||
.type!;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.put("$mangaId-filterChapterBookMark", type);
|
||||
var value = ChapterFilterBookmarked()
|
||||
..type = type
|
||||
..mangaId = mangaId;
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
List<ChapterFilterBookmarked>? chapterFilterBookmarkedList = [];
|
||||
for (var filterChapter in settings.chapterFilterBookmarkedList!) {
|
||||
if (filterChapter.mangaId != mangaId) {
|
||||
chapterFilterBookmarkedList.add(filterChapter);
|
||||
}
|
||||
}
|
||||
chapterFilterBookmarkedList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(
|
||||
settings..chapterFilterBookmarkedList = chapterFilterBookmarkedList);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ final isExtendedStateProvider =
|
|||
);
|
||||
|
||||
typedef _$IsExtendedState = AutoDisposeNotifier<bool>;
|
||||
String _$sortChapterStateHash() => r'38b241e06866613a0c34d306da0d855f57af3862';
|
||||
String _$sortChapterStateHash() => r'ff796f8f8ef4bf1c5b07694d24a68f28284b441e';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -79,10 +79,10 @@ class _SystemHash {
|
|||
}
|
||||
|
||||
abstract class _$SortChapterState
|
||||
extends BuildlessAutoDisposeNotifier<dynamic> {
|
||||
extends BuildlessAutoDisposeNotifier<SortChapter> {
|
||||
late final int mangaId;
|
||||
|
||||
dynamic build({
|
||||
SortChapter build({
|
||||
required int mangaId,
|
||||
});
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ abstract class _$SortChapterState
|
|||
const sortChapterStateProvider = SortChapterStateFamily();
|
||||
|
||||
/// See also [SortChapterState].
|
||||
class SortChapterStateFamily extends Family<dynamic> {
|
||||
class SortChapterStateFamily extends Family<SortChapter> {
|
||||
/// See also [SortChapterState].
|
||||
const SortChapterStateFamily();
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ class SortChapterStateFamily extends Family<dynamic> {
|
|||
|
||||
/// See also [SortChapterState].
|
||||
class SortChapterStateProvider
|
||||
extends AutoDisposeNotifierProviderImpl<SortChapterState, dynamic> {
|
||||
extends AutoDisposeNotifierProviderImpl<SortChapterState, SortChapter> {
|
||||
/// See also [SortChapterState].
|
||||
SortChapterStateProvider({
|
||||
required this.mangaId,
|
||||
|
|
@ -164,7 +164,7 @@ class SortChapterStateProvider
|
|||
}
|
||||
|
||||
@override
|
||||
dynamic runNotifierBuild(
|
||||
SortChapter runNotifierBuild(
|
||||
covariant SortChapterState notifier,
|
||||
) {
|
||||
return notifier.build(
|
||||
|
|
@ -174,7 +174,7 @@ class SortChapterStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterDownloadedStateHash() =>
|
||||
r'a19a077ae1caa5bd5b4cdcded1c41960e6fa86f2';
|
||||
r'3256f01a869af8c0681e1ff95ef6d942ca7f4f7b';
|
||||
|
||||
abstract class _$ChapterFilterDownloadedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -274,7 +274,7 @@ class ChapterFilterDownloadedStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterUnreadStateHash() =>
|
||||
r'f7d0609cb5dd9809c0f9af1e7931ad02e34b7569';
|
||||
r'edbd4bfa31345b1ecea561d46788b202aef8b646';
|
||||
|
||||
abstract class _$ChapterFilterUnreadState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -373,7 +373,7 @@ class ChapterFilterUnreadStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterBookmarkedStateHash() =>
|
||||
r'b0b0865a5d093ad0da01ed6c2e374a05e460d14a';
|
||||
r'45ccd61f2a2576ac20cc4ba275fad02b51568b8a';
|
||||
|
||||
abstract class _$ChapterFilterBookmarkedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class ChapterPageDownload extends ConsumerStatefulWidget {
|
|||
|
||||
class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
||||
with AutomaticKeepAliveClientMixin<ChapterPageDownload> {
|
||||
List _urll = [];
|
||||
List<String> _pageUrls = [];
|
||||
|
||||
final StorageProvider _storageProvider = StorageProvider();
|
||||
_startDownload() async {
|
||||
|
|
@ -32,7 +32,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
.watch(downloadChapterProvider(chapter: widget.chapter).future);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_urll = data;
|
||||
_pageUrls = data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -250,11 +250,8 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
setState(() {
|
||||
_isStarted = false;
|
||||
});
|
||||
List<String> taskIds = [];
|
||||
for (var id in _urll) {
|
||||
taskIds.add(id);
|
||||
}
|
||||
FileDownloader().cancelTasksWithIds(taskIds).then((value) async {
|
||||
|
||||
FileDownloader().cancelTasksWithIds(_pageUrls).then((value) async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
isar.writeTxnSync(() {
|
||||
int id = isar.downloads
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|||
part 'download_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<dynamic>> downloadChapter(
|
||||
Future<List<String>> downloadChapter(
|
||||
DownloadChapterRef ref, {
|
||||
required Chapter chapter,
|
||||
}) async {
|
||||
List pageUrls = [];
|
||||
List<String> pageUrls = [];
|
||||
List<DownloadTask> tasks = [];
|
||||
final StorageProvider storageProvider = StorageProvider();
|
||||
await storageProvider.requestPermission();
|
||||
|
|
@ -83,7 +83,7 @@ Future<List<dynamic>> downloadChapter(
|
|||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: headers(manga.source!),
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory:
|
||||
|
|
@ -104,7 +104,7 @@ Future<List<dynamic>> downloadChapter(
|
|||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: headers(manga.source!),
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isWindows ||
|
||||
|
|
@ -125,17 +125,14 @@ Future<List<dynamic>> downloadChapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
List<String> url = [];
|
||||
for (var a in pageUrls) {
|
||||
url.add(a);
|
||||
}
|
||||
|
||||
if (tasks.isEmpty && pageUrls.isNotEmpty) {
|
||||
final model = Download(
|
||||
succeeded: 0,
|
||||
failed: 0,
|
||||
total: 0,
|
||||
isDownload: true,
|
||||
taskIds: url,
|
||||
taskIds: pageUrls,
|
||||
isStartDownload: false,
|
||||
chapterId: chapter.id);
|
||||
|
||||
|
|
@ -156,7 +153,7 @@ Future<List<dynamic>> downloadChapter(
|
|||
failed: failed,
|
||||
total: tasks.length,
|
||||
isDownload: (succeeded == tasks.length) ? true : false,
|
||||
taskIds: url,
|
||||
taskIds: pageUrls,
|
||||
isStartDownload: true,
|
||||
chapterId: chapter.id,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'download_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$downloadChapterHash() => r'20b3014063b793031f0b0b8b358667f64cae5bd5';
|
||||
String _$downloadChapterHash() => r'c99c801fcfed7065161e0220625ebc8db49703c1';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -29,14 +29,14 @@ class _SystemHash {
|
|||
}
|
||||
}
|
||||
|
||||
typedef DownloadChapterRef = AutoDisposeFutureProviderRef<List<dynamic>>;
|
||||
typedef DownloadChapterRef = AutoDisposeFutureProviderRef<List<String>>;
|
||||
|
||||
/// See also [downloadChapter].
|
||||
@ProviderFor(downloadChapter)
|
||||
const downloadChapterProvider = DownloadChapterFamily();
|
||||
|
||||
/// See also [downloadChapter].
|
||||
class DownloadChapterFamily extends Family<AsyncValue<List<dynamic>>> {
|
||||
class DownloadChapterFamily extends Family<AsyncValue<List<String>>> {
|
||||
/// See also [downloadChapter].
|
||||
const DownloadChapterFamily();
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ class DownloadChapterFamily extends Family<AsyncValue<List<dynamic>>> {
|
|||
}
|
||||
|
||||
/// See also [downloadChapter].
|
||||
class DownloadChapterProvider extends AutoDisposeFutureProvider<List<dynamic>> {
|
||||
class DownloadChapterProvider extends AutoDisposeFutureProvider<List<String>> {
|
||||
/// See also [downloadChapter].
|
||||
DownloadChapterProvider({
|
||||
required this.chapter,
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ class _MangaHomeImageCardState extends ConsumerState<MangaHomeImageCard>
|
|||
return getMangaDetail.when(
|
||||
data: (data) {
|
||||
return MangaImageCardWidget(
|
||||
getMangaDetailModel: data,
|
||||
getMangaDetail: data,
|
||||
lang: widget.lang,
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:io';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:fast_cached_network_image/fast_cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
|
||||
class ImageViewHorizontal extends StatelessWidget {
|
||||
class ImageViewHorizontal extends ConsumerWidget {
|
||||
final int length;
|
||||
final String url;
|
||||
final int index;
|
||||
|
|
@ -34,7 +34,7 @@ class ImageViewHorizontal extends StatelessWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return isLocale
|
||||
? ExtendedImage.file(
|
||||
File("${path.path}" "${padIndex(index + 1)}.jpg"),
|
||||
|
|
@ -45,11 +45,12 @@ class ImageViewHorizontal extends StatelessWidget {
|
|||
onDoubleTap: onDoubleTap,
|
||||
loadStateChanged: loadStateChanged,
|
||||
)
|
||||
: ExtendedImage(
|
||||
image: FastCachedImageProvider(url, headers: headers(source)),
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
: ExtendedImage.network(
|
||||
url,
|
||||
headers: ref.watch(headersProvider(source: source)),
|
||||
enableMemoryCache: true,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
cacheMaxAge: const Duration(days: 7),
|
||||
initGestureConfigHandler: initGestureConfigHandler,
|
||||
onDoubleTap: onDoubleTap,
|
||||
handleLoadingProgress: true,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import 'dart:io';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:fast_cached_network_image/fast_cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
import 'package:mangayomi/views/manga/reader/widgets/circular_progress_indicator_animate_rotate.dart';
|
||||
|
||||
class ImageViewVertical extends StatefulWidget {
|
||||
class ImageViewVertical extends ConsumerWidget {
|
||||
final int length;
|
||||
final bool isLocale;
|
||||
final String url;
|
||||
|
|
@ -31,80 +31,72 @@ class ImageViewVertical extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
State<ImageViewVertical> createState() => _ImageViewVerticalState();
|
||||
}
|
||||
|
||||
class _ImageViewVerticalState extends State<ImageViewVertical>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Container(
|
||||
color: Colors.black,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (widget.index == 0)
|
||||
if (index == 0)
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).padding.top,
|
||||
),
|
||||
widget.isLocale
|
||||
isLocale
|
||||
? ExtendedImage.file(
|
||||
fit: BoxFit.contain,
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
File('${widget.path.path}${padIndex(widget.index + 1)}.jpg'))
|
||||
: ExtendedImage(
|
||||
image: FastCachedImageProvider(widget.url,
|
||||
headers: headers(widget.source)),
|
||||
File('${path.path}${padIndex(index + 1)}.jpg'))
|
||||
: ExtendedImage.network(url,
|
||||
headers: ref.watch(headersProvider(source: source)),
|
||||
handleLoadingProgress: true,
|
||||
cacheMaxAge: const Duration(days: 7),
|
||||
fit: BoxFit.contain,
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
enableMemoryCache: true,
|
||||
loadStateChanged: (ExtendedImageState state) {
|
||||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress =
|
||||
state.loadingProgress;
|
||||
final double progress =
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress =
|
||||
state.loadingProgress;
|
||||
final double progress =
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
color: Colors.black,
|
||||
height: mediaHeight(context, 0.8),
|
||||
child: CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.failed) {
|
||||
return Container(
|
||||
color: Colors.black,
|
||||
height: mediaHeight(context, 0.8),
|
||||
child: CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.failed) {
|
||||
return Container(
|
||||
color: Colors.black,
|
||||
height: mediaHeight(context, 0.8),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
state.reLoadImage();
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.replay_outlined,
|
||||
size: 30,
|
||||
)),
|
||||
],
|
||||
));
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
if (widget.index + 1 == widget.length)
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
state.reLoadImage();
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.replay_outlined,
|
||||
size: 30,
|
||||
)),
|
||||
],
|
||||
));
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
if (index + 1 == length)
|
||||
SizedBox(
|
||||
height: mediaHeight(context, 0.3),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'${widget.chapter} finished',
|
||||
'$chapter finished',
|
||||
style: const TextStyle(
|
||||
fontSize: 17.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
|
@ -127,7 +119,4 @@ class _ImageViewVerticalState extends State<ImageViewVertical>
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:mangayomi/models/chapter.dart';
|
|||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/reader_settings.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'reader_controller_provider.g.dart';
|
||||
|
|
@ -50,8 +50,7 @@ class ReaderController extends _$ReaderController {
|
|||
if (personalReaderMode.isNotEmpty) {
|
||||
return personalReaderMode.first.readerMode;
|
||||
}
|
||||
// return isar.readerSettings.getSync(227)!.defaultReaderMode;
|
||||
return ReaderMode.vertical;
|
||||
return isar.readerSettings.getSync(227)!.defaultReaderMode;
|
||||
}
|
||||
|
||||
String getReaderModeValue(ReaderMode readerMode) {
|
||||
|
|
@ -84,18 +83,19 @@ class ReaderController extends _$ReaderController {
|
|||
void setShowPageNumber(bool value) {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
ref
|
||||
.watch(hiveBoxMangaProvider)
|
||||
.put("${getSourceName()}/${getMangaName()}-showPagesNumber", value);
|
||||
isar.writeTxnSync(() =>
|
||||
isar.settings.putSync(getIsarSetting()..showPagesNumber = value));
|
||||
}
|
||||
}
|
||||
|
||||
Settings getIsarSetting() {
|
||||
return isar.settings.getSync(227)!;
|
||||
}
|
||||
|
||||
bool getShowPageNumber() {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
return ref.watch(hiveBoxMangaProvider).get(
|
||||
"${getSourceName()}/${getMangaName()}-showPagesNumber",
|
||||
defaultValue: true);
|
||||
return getIsarSetting().showPagesNumber!;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -208,12 +208,15 @@ class ReaderController extends _$ReaderController {
|
|||
|
||||
int getPageIndex() {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final index = getIsarSetting()
|
||||
.chapterPageIndexList!
|
||||
.where((element) => element.chapterId == chapter.id);
|
||||
if (!incognitoMode) {
|
||||
return chapter.isRead!
|
||||
? 0
|
||||
: ref.watch(hiveBoxMangaProvider).get(
|
||||
"${getSourceName()}/${getMangaName()}/${getChapterTitle()}-page_index",
|
||||
defaultValue: 0);
|
||||
: index.isNotEmpty
|
||||
? index.first.index!
|
||||
: 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -221,21 +224,30 @@ class ReaderController extends _$ReaderController {
|
|||
int getPageLength(List incognitoPageLength) {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
List<dynamic> page = ref.watch(hiveBoxMangaProvider).get(
|
||||
"${getSourceName()}/${getMangaName()}/${getChapterTitle()}-pageurl",
|
||||
);
|
||||
return page.length;
|
||||
return getIsarSetting()
|
||||
.chapterPageUrlsList!
|
||||
.where((element) => element.chapterId == chapter.id)
|
||||
.first
|
||||
.urls!
|
||||
.length;
|
||||
}
|
||||
return incognitoPageLength.length;
|
||||
}
|
||||
|
||||
void setPageIndex(int newIndex) {
|
||||
// log(newIndex.toString());
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
ref.watch(hiveBoxMangaProvider).put(
|
||||
"${getSourceName()}/${getMangaName()}/${getChapterTitle()}-page_index",
|
||||
newIndex);
|
||||
List<ChapterPageIndex>? chapterPageIndexs = [];
|
||||
for (var chapterPageIndex in getIsarSetting().chapterPageIndexList!) {
|
||||
if (chapterPageIndex.chapterId != chapter.id) {
|
||||
chapterPageIndexs.add(chapterPageIndex);
|
||||
}
|
||||
}
|
||||
chapterPageIndexs.add(ChapterPageIndex()
|
||||
..chapterId = chapter.id
|
||||
..index = newIndex);
|
||||
isar.writeTxnSync(() => isar.settings
|
||||
.putSync(getIsarSetting()..chapterPageIndexList = chapterPageIndexs));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +256,7 @@ class ReaderController extends _$ReaderController {
|
|||
}
|
||||
|
||||
String getSourceName() {
|
||||
return '${getManga().lang}-${getManga().source!}';
|
||||
return getManga().source!;
|
||||
}
|
||||
|
||||
String getChapterTitle() {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class CurrentIndexProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$readerControllerHash() => r'bc59a95312515f4609f994e30ab996268d08a7a8';
|
||||
String _$readerControllerHash() => r'f7b59c997f224f05d925ff8ccea2eb67d10ef5ea';
|
||||
|
||||
abstract class _$ReaderController extends BuildlessAutoDisposeNotifier<void> {
|
||||
late final Chapter chapter;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'blend_level_state_provider.g.dart';
|
||||
|
||||
|
|
@ -6,11 +7,13 @@ part 'blend_level_state_provider.g.dart';
|
|||
class BlendLevelState extends _$BlendLevelState {
|
||||
@override
|
||||
double build() {
|
||||
return ref.watch(hiveBoxSettingsProvider).get('blendLevel', defaultValue: 10.0)!;
|
||||
return isar.settings.getSync(227)!.flexColorSchemeBlendLevel!;
|
||||
}
|
||||
|
||||
void setBlendLevel(double blendLevelValue) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = blendLevelValue;
|
||||
ref.watch(hiveBoxSettingsProvider).put('blendLevel', state);
|
||||
isar.writeTxnSync(() =>
|
||||
isar.settings.putSync(settings!..flexColorSchemeBlendLevel = state));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'blend_level_state_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$blendLevelStateHash() => r'b1a14a5ff8ddf89164aec31c92c24ec9585ce0f5';
|
||||
String _$blendLevelStateHash() => r'4928d5e9bc01d7ee9378458cd4d6a294248e10a4';
|
||||
|
||||
/// See also [BlendLevelState].
|
||||
@ProviderFor(BlendLevelState)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'date_format_state_provider.g.dart';
|
||||
|
||||
|
|
@ -6,14 +7,14 @@ part 'date_format_state_provider.g.dart';
|
|||
class DateFormatState extends _$DateFormatState {
|
||||
@override
|
||||
String build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('dateFormat', defaultValue: "M/d/y")!;
|
||||
return isar.settings.getSync(227)!.dateFormat!;
|
||||
}
|
||||
|
||||
void set(String dateFormat) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = dateFormat;
|
||||
ref.watch(hiveBoxSettingsProvider).put('dateFormat', state);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..dateFormat = state));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -21,13 +22,13 @@ class DateFormatState extends _$DateFormatState {
|
|||
class RelativeTimesTampsState extends _$RelativeTimesTampsState {
|
||||
@override
|
||||
int build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('relativeTimesTamps', defaultValue: 2)!;
|
||||
return isar.settings.getSync(227)!.relativeTimesTamps!;
|
||||
}
|
||||
|
||||
void set(int type) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = type;
|
||||
ref.watch(hiveBoxSettingsProvider).put('relativeTimesTamps', state);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..relativeTimesTamps = state));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'date_format_state_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$dateFormatStateHash() => r'e2f6488fdd5026c04f1c8293ccf73575b07382f5';
|
||||
String _$dateFormatStateHash() => r'094aa68b09b654de97be6a59c6d593f30e3bdf79';
|
||||
|
||||
/// See also [DateFormatState].
|
||||
@ProviderFor(DateFormatState)
|
||||
|
|
@ -23,7 +23,7 @@ final dateFormatStateProvider =
|
|||
|
||||
typedef _$DateFormatState = AutoDisposeNotifier<String>;
|
||||
String _$relativeTimesTampsStateHash() =>
|
||||
r'6248d82c1f8d1e764524b3ac7527a34701843615';
|
||||
r'e515ea30e71143ee60f86a02320e8b1f50b5a955';
|
||||
|
||||
/// See also [RelativeTimesTampsState].
|
||||
@ProviderFor(RelativeTimesTampsState)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'flex_scheme_color_state_provider.g.dart';
|
||||
|
|
@ -8,22 +9,18 @@ part 'flex_scheme_color_state_provider.g.dart';
|
|||
class FlexSchemeColorState extends _$FlexSchemeColorState {
|
||||
@override
|
||||
FlexSchemeColor build() {
|
||||
final flexSchemeColorIndex =
|
||||
isar.settings.getSync(227)!.flexSchemeColorIndex!;
|
||||
return ref.read(themeModeStateProvider)
|
||||
? ThemeAA
|
||||
.schemes[ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('FlexColorIndex', defaultValue: 2)]
|
||||
.light
|
||||
: ThemeAA
|
||||
.schemes[ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('FlexColorIndex', defaultValue: 2)]
|
||||
.dark;
|
||||
? ThemeAA.schemes[flexSchemeColorIndex].light
|
||||
: ThemeAA.schemes[flexSchemeColorIndex].dark;
|
||||
}
|
||||
|
||||
void setTheme(FlexSchemeColor color, int index) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = color;
|
||||
ref.watch(hiveBoxSettingsProvider).put('FlexColorIndex', index);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..flexSchemeColorIndex = index));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ part of 'flex_scheme_color_state_provider.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$flexSchemeColorStateHash() =>
|
||||
r'84c6afce63762e5704c548caf9059f922a9936b8';
|
||||
r'a8b6bdbfce0d97a3fd9f95fceea81205e275a4b4';
|
||||
|
||||
/// See also [FlexSchemeColorState].
|
||||
@ProviderFor(FlexSchemeColorState)
|
||||
|
|
|
|||
|
|
@ -1,22 +1,33 @@
|
|||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/flex_scheme_color_state_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'theme_mode_state_provider.g.dart';
|
||||
|
||||
|
||||
@riverpod
|
||||
class ThemeModeState extends _$ThemeModeState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref.watch(hiveBoxSettingsProvider).get('isLight', defaultValue: true)!;
|
||||
return isar.settings.getSync(227)!.themeIsDark!;
|
||||
}
|
||||
|
||||
void setLightTheme() {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = true;
|
||||
ref.watch(hiveBoxSettingsProvider).put('isLight', state);
|
||||
ref.read(flexSchemeColorStateProvider.notifier).setTheme(
|
||||
ThemeAA.schemes[settings!.flexSchemeColorIndex!].light,
|
||||
settings.flexSchemeColorIndex!);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings..themeIsDark = state));
|
||||
}
|
||||
|
||||
void setDarkTheme() {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = false;
|
||||
ref.watch(hiveBoxSettingsProvider).put('isLight', state);
|
||||
ref.read(flexSchemeColorStateProvider.notifier).setTheme(
|
||||
ThemeAA.schemes[settings!.flexSchemeColorIndex!].dark,
|
||||
settings.flexSchemeColorIndex!);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings..themeIsDark = state));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'theme_mode_state_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$themeModeStateHash() => r'ffb06bbf255e51a6f14424280f7874b1a11062ec';
|
||||
String _$themeModeStateHash() => r'6b366dcb03de67cfd2d792d3a9e6678da9e6869c';
|
||||
|
||||
/// See also [ThemeModeState].
|
||||
@ProviderFor(ThemeModeState)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/flex_scheme_color_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||
// import 'package:rive/rive.dart';
|
||||
|
||||
|
|
@ -18,24 +16,15 @@ class DarkModeButton extends ConsumerStatefulWidget {
|
|||
class _DarkModeButtonState extends ConsumerState<DarkModeButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isLight = ref.watch(themeModeStateProvider);
|
||||
bool isDark = ref.watch(themeModeStateProvider);
|
||||
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
int flexColorIndex = ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('FlexColorIndex', defaultValue: 7);
|
||||
if (!isLight == true) {
|
||||
if (!isDark) {
|
||||
ref.read(themeModeStateProvider.notifier).setLightTheme();
|
||||
} else {
|
||||
ref.read(themeModeStateProvider.notifier).setDarkTheme();
|
||||
}
|
||||
|
||||
!isLight
|
||||
? ref.read(flexSchemeColorStateProvider.notifier).setTheme(
|
||||
ThemeAA.schemes[flexColorIndex].light, flexColorIndex)
|
||||
: ref.read(flexSchemeColorStateProvider.notifier).setTheme(
|
||||
ThemeAA.schemes[flexColorIndex].dark, flexColorIndex);
|
||||
},
|
||||
title: const Text("Dark mode"),
|
||||
subtitle: Text(
|
||||
|
|
@ -43,9 +32,9 @@ class _DarkModeButtonState extends ConsumerState<DarkModeButton> {
|
|||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
trailing: Switch(
|
||||
value: !isLight,
|
||||
value: !isDark,
|
||||
onChanged: (dd) {
|
||||
if (!isLight == true) {
|
||||
if (!isDark) {
|
||||
ref.read(themeModeStateProvider.notifier).setLightTheme();
|
||||
} else {
|
||||
ref.read(themeModeStateProvider.notifier).setDarkTheme();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import 'package:flex_color_scheme/flex_color_scheme.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/flex_scheme_color_state_provider.dart';
|
||||
|
||||
|
|
@ -20,8 +21,7 @@ class ThemeSelector extends ConsumerStatefulWidget {
|
|||
class _ThemeSelectorState extends ConsumerState<ThemeSelector> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int selected =
|
||||
ref.watch(hiveBoxSettingsProvider).get('FlexColorIndex', defaultValue: 7);
|
||||
int selected = isar.settings.getSync(227)!.flexSchemeColorIndex!;
|
||||
const double height = 45;
|
||||
const double width = height * 1.5;
|
||||
final ThemeData theme = Theme.of(context);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'incognito_mode_state_provider.g.dart';
|
||||
|
||||
|
|
@ -6,13 +7,13 @@ part 'incognito_mode_state_provider.g.dart';
|
|||
class IncognitoModeState extends _$IncognitoModeState {
|
||||
@override
|
||||
bool build() {
|
||||
return ref
|
||||
.watch(hiveBoxSettingsProvider)
|
||||
.get('incognitoMode', defaultValue: false)!;
|
||||
return isar.settings.getSync(227)!.incognitoMode!;
|
||||
}
|
||||
|
||||
void setIncognitoMode(bool value) {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
state = value;
|
||||
ref.watch(hiveBoxSettingsProvider).put('incognitoMode', state);
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings..incognitoMode = state));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ part of 'incognito_mode_state_provider.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$incognitoModeStateHash() =>
|
||||
r'004cbf630f6431dcbaf87f4ac5dca0e2c96e689e';
|
||||
r'54fc89df3bffd0b9665f04d9c9c2f75532925804';
|
||||
|
||||
/// See also [IncognitoModeState].
|
||||
@ProviderFor(IncognitoModeState)
|
||||
|
|
|
|||
|
|
@ -1,84 +1,134 @@
|
|||
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/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/sources/service.dart';
|
||||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||
|
||||
class MangaImageCardWidget extends StatelessWidget {
|
||||
class MangaImageCardWidget extends ConsumerWidget {
|
||||
final String lang;
|
||||
final bool isLoading;
|
||||
|
||||
final GetManga? getMangaDetailModel;
|
||||
final GetManga? getMangaDetail;
|
||||
|
||||
const MangaImageCardWidget({
|
||||
required this.lang,
|
||||
super.key,
|
||||
this.isLoading = false,
|
||||
required this.getMangaDetailModel,
|
||||
required this.getMangaDetail,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final manga = Manga(
|
||||
imageUrl: getMangaDetailModel!.imageUrl,
|
||||
name: getMangaDetailModel!.name,
|
||||
genre: getMangaDetailModel!.genre,
|
||||
author: getMangaDetailModel!.author,
|
||||
status: getMangaDetailModel!.status,
|
||||
description: getMangaDetailModel!.description,
|
||||
link: getMangaDetailModel!.url,
|
||||
source: getMangaDetailModel!.source,
|
||||
lang: lang,
|
||||
lastUpdate: DateTime.now().millisecondsSinceEpoch);
|
||||
|
||||
final empty = isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(getMangaDetailModel!.name)
|
||||
.sourceEqualTo(getMangaDetailModel!.source)
|
||||
.isEmptySync();
|
||||
if (empty) {
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(manga);
|
||||
for (var i = 0; i < getMangaDetailModel!.chapters.length; i++) {
|
||||
final chapters = Chapter(
|
||||
name: getMangaDetailModel!.chapters[i].name,
|
||||
url: getMangaDetailModel!.chapters[i].url,
|
||||
dateUpload: getMangaDetailModel!.chapters[i].dateUpload,
|
||||
scanlator: getMangaDetailModel!.chapters[i].scanlator,
|
||||
mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
isar.chapters.putSync(chapters);
|
||||
chapters.manga.saveSync();
|
||||
}
|
||||
});
|
||||
}
|
||||
final mangaId = isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(getMangaDetailModel!.name)
|
||||
.sourceEqualTo(getMangaDetailModel!.source)
|
||||
.findFirstSync()!
|
||||
.id!;
|
||||
context.push('/manga-reader/detail', extra: mangaId);
|
||||
pushToMangaReaderDetail(
|
||||
context: context, getManga: getMangaDetail!, lang: lang);
|
||||
},
|
||||
child: CoverViewWidget(children: [
|
||||
cachedNetworkImage(
|
||||
headers: headers(getMangaDetailModel!.source!),
|
||||
imageUrl: getMangaDetailModel!.imageUrl!,
|
||||
headers:
|
||||
ref.watch(headersProvider(source: getMangaDetail!.source!)),
|
||||
imageUrl: getMangaDetail!.imageUrl!,
|
||||
width: 200,
|
||||
height: 270,
|
||||
fit: BoxFit.cover),
|
||||
BottomTextWidget(text: getMangaDetailModel!.name!)
|
||||
BottomTextWidget(text: getMangaDetail!.name!)
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void pushToMangaReaderDetail(
|
||||
{GetManga? getManga,
|
||||
required String lang,
|
||||
required BuildContext context,
|
||||
Manga? mangaM}) {
|
||||
final manga = mangaM ??
|
||||
Manga(
|
||||
imageUrl: getManga!.imageUrl,
|
||||
name: getManga.name,
|
||||
genre: getManga.genre,
|
||||
author: getManga.author,
|
||||
status: getManga.status,
|
||||
description: getManga.description,
|
||||
link: getManga.url,
|
||||
source: getManga.source,
|
||||
lang: lang,
|
||||
lastUpdate: DateTime.now().millisecondsSinceEpoch);
|
||||
|
||||
final empty = isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(manga.name)
|
||||
.sourceEqualTo(manga.source)
|
||||
.isEmptySync();
|
||||
if (empty) {
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(manga);
|
||||
for (var i = 0; i < manga.chapters.length; i++) {
|
||||
final chapters = Chapter(
|
||||
name: manga.chapters.toList()[i].name,
|
||||
url: manga.chapters.toList()[i].url,
|
||||
dateUpload: manga.chapters.toList()[i].dateUpload,
|
||||
scanlator: manga.chapters.toList()[i].scanlator,
|
||||
mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
isar.chapters.putSync(chapters);
|
||||
chapters.manga.saveSync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final mangaId = isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(manga.name)
|
||||
.sourceEqualTo(manga.source)
|
||||
.findFirstSync()!
|
||||
.id!;
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
final checkIfExist = settings.sortChapterList!
|
||||
.where((element) => element.mangaId == mangaId)
|
||||
.toList();
|
||||
if (checkIfExist.isEmpty) {
|
||||
isar.writeTxnSync(
|
||||
() {
|
||||
List<SortChapter>? sortChapterList = [];
|
||||
for (var sortChapter in settings.sortChapterList!) {
|
||||
sortChapterList.add(sortChapter);
|
||||
}
|
||||
List<ChapterFilterBookmarked>? chapterFilterBookmarkedList = [];
|
||||
for (var sortChapter in settings.chapterFilterBookmarkedList!) {
|
||||
chapterFilterBookmarkedList.add(sortChapter);
|
||||
}
|
||||
List<ChapterFilterDownloaded>? chapterFilterDownloadedList = [];
|
||||
for (var sortChapter in settings.chapterFilterDownloadedList!) {
|
||||
chapterFilterDownloadedList.add(sortChapter);
|
||||
}
|
||||
List<ChapterFilterUnread>? chapterFilterUnreadList = [];
|
||||
for (var sortChapter in settings.chapterFilterUnreadList!) {
|
||||
chapterFilterUnreadList.add(sortChapter);
|
||||
}
|
||||
sortChapterList.add(SortChapter()..mangaId = mangaId);
|
||||
chapterFilterBookmarkedList
|
||||
.add(ChapterFilterBookmarked()..mangaId = mangaId);
|
||||
chapterFilterDownloadedList
|
||||
.add(ChapterFilterDownloaded()..mangaId = mangaId);
|
||||
chapterFilterUnreadList.add(ChapterFilterUnread()..mangaId = mangaId);
|
||||
isar.settings.putSync(settings
|
||||
..sortChapterList = sortChapterList
|
||||
..chapterFilterBookmarkedList = chapterFilterBookmarkedList
|
||||
..chapterFilterDownloadedList = chapterFilterDownloadedList
|
||||
..chapterFilterUnreadList = chapterFilterUnreadList);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
context.push('/manga-reader/detail', extra: mangaId);
|
||||
}
|
||||
|
|
|
|||
58
pubspec.lock
58
pubspec.lock
|
|
@ -274,14 +274,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
dio:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dio
|
||||
sha256: "0894a098594263fe1caaba3520e3016d8a855caeb010a882273189cca10f11e9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
draggable_menu:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -330,14 +322,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
fast_cached_network_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fast_cached_network_image
|
||||
sha256: "78a2da7314008540fce494906d017adc7654edbd259dca24c0a9b5fd78cdcd5c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -392,7 +376,7 @@ packages:
|
|||
source: hosted
|
||||
version: "0.7.0"
|
||||
flutter_cache_manager:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3"
|
||||
|
|
@ -526,30 +510,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.2"
|
||||
hive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hive
|
||||
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
hive_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hive_flutter
|
||||
sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
hive_generator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hive_generator
|
||||
sha256: "65998cc4d2cd9680a3d9709d893d2f6bb15e6c1f92626c3f1fa650b4b3281521"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
html:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -910,14 +870,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
random_string:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: random_string
|
||||
sha256: "03b52435aae8cbdd1056cf91bfc5bf845e9706724dd35ae2e99fa14a1ef79d02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -995,14 +947,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.7"
|
||||
source_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_helper
|
||||
sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ dependencies:
|
|||
go_router: ^6.5.2
|
||||
flutter_riverpod: ^2.3.2
|
||||
cached_network_image: ^3.2.3
|
||||
hive_flutter: ^1.1.0
|
||||
hive_generator: ^2.0.0
|
||||
hive: ^2.2.3
|
||||
http: ^0.13.5
|
||||
riverpod_annotation: ^2.0.2
|
||||
html: ^0.15.2
|
||||
|
|
@ -59,10 +56,7 @@ dependencies:
|
|||
url: https://github.com/kodjodevf/background_downloader.git
|
||||
permission_handler: ^10.2.0
|
||||
flutter_inappwebview: ^6.0.0-beta.22
|
||||
flutter_cache_manager: ^3.3.0
|
||||
draggable_menu: ^2.0.2
|
||||
fast_cached_network_image: ^1.2.0
|
||||
random_string: ^2.3.1
|
||||
isar: 3.1.0+1
|
||||
isar_flutter_libs: 3.1.0+1
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue