Finish migration hive to isar database & big changes

This commit is contained in:
kodjomoustapha 2023-05-17 14:22:19 +01:00
parent 181647512e
commit 07b8f4303a
70 changed files with 7790 additions and 1192 deletions

View file

@ -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() {

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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

View file

@ -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, '_')}/");
}
}

View file

@ -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()) {

View file

@ -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 {

View file

@ -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!;
}

View file

@ -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 {

View file

@ -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!;
}

View file

@ -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 {

View file

@ -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!;
}

View 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

View file

@ -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);
}
}

View 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

View file

@ -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));
}
}

View file

@ -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

View file

@ -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;

View 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

View file

@ -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!;

View file

@ -6,7 +6,7 @@ part of 'search_manga.dart';
// RiverpodGenerator
// **************************************************************************
String _$searchMangaHash() => r'4f5160d862404936b098269fe913bda960deb039';
String _$searchMangaHash() => r'0d71677c6ef2822590f2061119134e3b0e3167f7';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -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))),
),

View file

@ -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()});

View file

@ -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();
// }
// }

View file

@ -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!);
}
}
}

View file

@ -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="([^"]+)"');

View file

@ -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 {

View file

@ -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;
}

View file

@ -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" : ""}";
}

View file

@ -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;

View file

@ -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'\\[(.*?)\\]'), '')

View file

@ -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

View file

@ -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";

View file

@ -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
View 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

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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);
}),
],
),
)
],
),
);
}),
]),
),
],
);
}),
]),
),
],
),
),
))));
}

View file

@ -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!;
}
}

View file

@ -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].

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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;
}

View file

@ -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> {

View file

@ -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

View file

@ -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,
);

View file

@ -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,

View file

@ -274,7 +274,7 @@ class _MangaHomeImageCardState extends ConsumerState<MangaHomeImageCard>
return getMangaDetail.when(
data: (data) {
return MangaImageCardWidget(
getMangaDetailModel: data,
getMangaDetail: data,
lang: widget.lang,
);
},

View file

@ -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,

View file

@ -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;
}

View file

@ -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() {

View file

@ -123,7 +123,7 @@ class CurrentIndexProvider
}
}
String _$readerControllerHash() => r'bc59a95312515f4609f994e30ab996268d08a7a8';
String _$readerControllerHash() => r'f7b59c997f224f05d925ff8ccea2eb67d10ef5ea';
abstract class _$ReaderController extends BuildlessAutoDisposeNotifier<void> {
late final Chapter chapter;

View file

@ -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));
}
}

View file

@ -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)

View file

@ -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));
}
}

View file

@ -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)

View file

@ -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));
}
}

View file

@ -7,7 +7,7 @@ part of 'flex_scheme_color_state_provider.dart';
// **************************************************************************
String _$flexSchemeColorStateHash() =>
r'84c6afce63762e5704c548caf9059f922a9936b8';
r'a8b6bdbfce0d97a3fd9f95fceea81205e275a4b4';
/// See also [FlexSchemeColorState].
@ProviderFor(FlexSchemeColorState)

View file

@ -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));
}
}

View file

@ -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)

View file

@ -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();

View file

@ -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);

View file

@ -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));
}
}

View file

@ -7,7 +7,7 @@ part of 'incognito_mode_state_provider.dart';
// **************************************************************************
String _$incognitoModeStateHash() =>
r'004cbf630f6431dcbaf87f4ac5dca0e2c96e689e';
r'54fc89df3bffd0b9665f04d9c9c2f75532925804';
/// See also [IncognitoModeState].
@ProviderFor(IncognitoModeState)

View file

@ -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);
}

View file

@ -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:

View file

@ -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