source: add mangadex

This commit is contained in:
kodjomoustapha 2023-06-08 16:36:13 +01:00
parent 1a40116e1d
commit 3d6b07de02
47 changed files with 1695 additions and 98 deletions

View file

@ -58,4 +58,11 @@ class Manga {
});
}
enum Status { ongoing, completed, canceled, unknown, onHiatus }
enum Status {
ongoing,
completed,
canceled,
unknown,
onHiatus,
publishingFinished
}

View file

@ -276,6 +276,7 @@ const _MangastatusEnumValueMap = {
'canceled': 2,
'unknown': 3,
'onHiatus': 4,
'publishingFinished': 5,
};
const _MangastatusValueEnumMap = {
0: Status.ongoing,
@ -283,6 +284,7 @@ const _MangastatusValueEnumMap = {
2: Status.canceled,
3: Status.unknown,
4: Status.onHiatus,
5: Status.publishingFinished,
};
Id _mangaGetId(Manga object) {

View file

@ -68,5 +68,7 @@ enum TypeSource {
heancms,
madara
madara,
mangadex
}

View file

@ -261,6 +261,7 @@ const _SourcetypeSourceEnumValueMap = {
'mmrcms': 3,
'heancms': 4,
'madara': 5,
'mangadex': 6,
};
const _SourcetypeSourceValueEnumMap = {
0: TypeSource.single,
@ -269,6 +270,7 @@ const _SourcetypeSourceValueEnumMap = {
3: TypeSource.mmrcms,
4: TypeSource.heancms,
5: TypeSource.madara,
6: TypeSource.mangadex,
};
Id _sourceGetId(Source object) {

View file

@ -89,8 +89,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, lang: source.lang!));
return Scaffold(
body: SizedBox(
height: 260,

View file

@ -473,7 +473,7 @@ class ChapterFilterBookmarkedStateProvider
}
String _$chapterFilterResultStateHash() =>
r'efd09e7ec1bc7f63ffdcc82c5c2760de94d704e6';
r'ed7adcf7a9d34c3614547735b48789bb004f49cd';
abstract class _$ChapterFilterResultState
extends BuildlessAutoDisposeNotifier<bool> {

View file

@ -51,7 +51,7 @@ class ReadMoreWidgetState extends State<ReadMoreWidget>
left: 0,
child: Container(
width: mediaWidth(context, 1),
height: 20,
height: 30,
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
gradient: LinearGradient(

View file

@ -54,14 +54,20 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
@override
Widget build(BuildContext context) {
if (_selectedIndex == 2 && _isSearch && _query.isNotEmpty) {
_getManga = ref.watch(
searchMangaProvider(source: widget.mangaType.source!, query: _query));
_getManga = ref.watch(searchMangaProvider(
source: widget.mangaType.source!,
query: _query,
lang: widget.mangaType.lang!));
} else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) {
_getManga = ref.watch(getLatestUpdatesMangaProvider(
source: widget.mangaType.source!, page: 1));
source: widget.mangaType.source!,
page: 1,
lang: widget.mangaType.lang!));
} else if (_selectedIndex == 0 && !_isSearch && _query.isEmpty) {
_getManga = ref.watch(
getPopularMangaProvider(source: widget.mangaType.source!, page: 1));
_getManga = ref.watch(getPopularMangaProvider(
source: widget.mangaType.source!,
page: 1,
lang: widget.mangaType.lang!));
}
return Scaffold(
@ -205,7 +211,8 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
.watch(getPopularMangaProvider(
source:
widget.mangaType.source!,
page: _page)
page: _page,
lang: widget.mangaType.lang!)
.future)
.then(
(value) {
@ -270,7 +277,9 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
}
ref
.watch(getPopularMangaProvider(
source: widget.mangaType.source!, page: _page)
source: widget.mangaType.source!,
page: _page,
lang: widget.mangaType.lang!)
.future)
.then(
(value) {

View file

@ -101,7 +101,8 @@ class SearchResultScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final search = ref.watch(searchMangaProvider(source: source, query: query));
final search = ref
.watch(searchMangaProvider(source: source, query: query, lang: lang));
return Scaffold(
appBar: viewOnly
? AppBar(

View file

@ -959,7 +959,6 @@ class _MangaChapterPageGalleryState
preloadPagesCount: _isZoom
? 0
: widget.readerController.getPageLength(widget.url),
pageSnapping: false,
canScrollPage: (GestureDetails? gestureDetails) {
return gestureDetails != null
? !(gestureDetails.totalScale! > 1.0)

View file

@ -54,7 +54,8 @@ class ReaderController extends _$ReaderController {
void setReaderMode(ReaderMode newReaderMode) {
List<PersonalReaderMode>? personalReaderModeLists = [];
for (var personalReaderMode in getIsarSetting().personalReaderModeList!) {
for (var personalReaderMode
in getIsarSetting().personalReaderModeList ?? []) {
if (personalReaderMode.mangaId != getManga().id) {
personalReaderModeLists.add(personalReaderMode);
}

View file

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

View file

@ -11,6 +11,7 @@ import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
import 'package:mangayomi/sources/src/all/mangadex/src/mangadex.dart';
import 'package:mangayomi/sources/src/en/mangahere/src/mangahere.dart';
import 'package:mangayomi/sources/src/fr/japscan/src/japscan.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/src/mangakawaii.dart';
@ -125,6 +126,14 @@ Future<GetChapterUrlModel> getChapterUrl(
pageUrls = await Madara().getChapterUrl(chapter: chapter, ref: ref);
}
/***********/
/*mangadex*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.mangadex) {
pageUrls = await MangaDex().getChapterUrl(chapter: chapter, ref: ref);
}
if (pageUrls.isNotEmpty) {
if (!incognitoMode) {
List<ChapterPageurls>? chapterPageUrls = [];

View file

@ -6,7 +6,7 @@ part of 'get_chapter_url.dart';
// RiverpodGenerator
// **************************************************************************
String _$getChapterUrlHash() => r'2e7729424ee0fc2b9a38bb0e25a1d109e7f3a3f7';
String _$getChapterUrlHash() => r'7d96750b6f404a08c44cc58be552ad291c5e18f8';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
import 'package:mangayomi/sources/src/all/mangadex/src/mangadex.dart';
import 'package:mangayomi/sources/src/en/mangahere/src/mangahere.dart';
import 'package:mangayomi/sources/src/fr/japscan/src/japscan.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/src/mangakawaii.dart';
@ -14,8 +15,12 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_latest_updates_manga.g.dart';
@riverpod
Future<List<GetManga?>> getLatestUpdatesManga(GetLatestUpdatesMangaRef ref,
{required String source, required int page}) async {
Future<List<GetManga?>> getLatestUpdatesManga(
GetLatestUpdatesMangaRef ref, {
required String source,
required int page,
required String lang,
}) async {
List<GetManga?>? latestUpdatesManga;
source = source.toLowerCase();
@ -23,24 +28,24 @@ Future<List<GetManga?>> getLatestUpdatesManga(GetLatestUpdatesMangaRef ref,
/*comick*/
/*******/
if (getMangaTypeSource(source) == TypeSource.comick) {
latestUpdatesManga =
await Comick().getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await Comick().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***************/
/*mangathemesia*/
/**************/
if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
latestUpdatesManga = await MangaThemeSia()
.getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await MangaThemeSia().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*mangakawaii*/
/***********/
if (source == "mangakawaii") {
latestUpdatesManga = await MangaKawaii()
.getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await MangaKawaii().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
@ -48,38 +53,47 @@ Future<List<GetManga?>> getLatestUpdatesManga(GetLatestUpdatesMangaRef ref,
/***********/
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
latestUpdatesManga =
await Mmrcms().getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await Mmrcms().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*mangahere*/
/***********/
else if (source == "mangahere") {
latestUpdatesManga =
await Mangahere().getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await Mangahere().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*japscan*/
/***********/
else if (source == "japscan") {
latestUpdatesManga =
await Japscan().getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await Japscan().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*heancms*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.heancms) {
latestUpdatesManga =
await HeanCms().getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await HeanCms().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*madara*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.madara) {
latestUpdatesManga =
await Madara().getLatestUpdatesManga(source: source, page: page, ref: ref);
latestUpdatesManga = await Madara().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*mangadex*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.mangadex) {
latestUpdatesManga = await MangaDex().getLatestUpdatesManga(
source: source, page: page, ref: ref, lang: lang);
}
return latestUpdatesManga!;
}

View file

@ -7,7 +7,7 @@ part of 'get_latest_updates_manga.dart';
// **************************************************************************
String _$getLatestUpdatesMangaHash() =>
r'2f6c7714feca588ada6c6dd98ad62849042e9bae';
r'c5ddc8739ee5b7c085cdeede7c55743bfc7f5120';
/// Copied from Dart SDK
class _SystemHash {
@ -46,10 +46,12 @@ class GetLatestUpdatesMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
GetLatestUpdatesMangaProvider call({
required String source,
required int page,
required String lang,
}) {
return GetLatestUpdatesMangaProvider(
source: source,
page: page,
lang: lang,
);
}
@ -60,6 +62,7 @@ class GetLatestUpdatesMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
return call(
source: provider.source,
page: provider.page,
lang: provider.lang,
);
}
@ -85,11 +88,13 @@ class GetLatestUpdatesMangaProvider
GetLatestUpdatesMangaProvider({
required this.source,
required this.page,
required this.lang,
}) : super.internal(
(ref) => getLatestUpdatesManga(
ref,
source: source,
page: page,
lang: lang,
),
from: getLatestUpdatesMangaProvider,
name: r'getLatestUpdatesMangaProvider',
@ -104,12 +109,14 @@ class GetLatestUpdatesMangaProvider
final String source;
final int page;
final String lang;
@override
bool operator ==(Object other) {
return other is GetLatestUpdatesMangaProvider &&
other.source == source &&
other.page == page;
other.page == page &&
other.lang == lang;
}
@override
@ -117,6 +124,7 @@ class GetLatestUpdatesMangaProvider
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, source.hashCode);
hash = _SystemHash.combine(hash, page.hashCode);
hash = _SystemHash.combine(hash, lang.hashCode);
return _SystemHash.finish(hash);
}

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
import 'package:mangayomi/sources/src/all/mangadex/src/mangadex.dart';
import 'package:mangayomi/sources/src/en/mangahere/src/mangahere.dart';
import 'package:mangayomi/sources/src/fr/japscan/src/japscan.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/src/mangakawaii.dart';
@ -87,5 +88,14 @@ Future<GetManga> getMangaDetail(GetMangaDetailRef ref,
mangadetail = await Madara()
.getMangaDetail(manga: manga, lang: lang, source: source, ref: ref);
}
/***********/
/*mangadex*/
/***********/
else if (getMangaTypeSource(source.toLowerCase()) == TypeSource.mangadex) {
mangadetail = await MangaDex()
.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'ecad72288b8df330f295949d2b452b1bffa132a9';
String _$getMangaDetailHash() => r'009422e0d88c595e2a8183e2360708ad2e13a955';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
import 'package:mangayomi/sources/src/all/mangadex/src/mangadex.dart';
import 'package:mangayomi/sources/src/en/mangahere/src/mangahere.dart';
import 'package:mangayomi/sources/src/fr/japscan/src/japscan.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/src/mangakawaii.dart';
@ -15,7 +16,7 @@ part 'get_popular_manga.g.dart';
@riverpod
Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
{required String source, required int page}) async {
{required String source, required int page, required String lang}) async {
List<GetManga?>? popularManga;
source = source.toLowerCase();
@ -23,8 +24,8 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
/*comick*/
/*******/
if (getMangaTypeSource(source) == TypeSource.comick) {
popularManga =
await Comick().getPopularManga(source: source, page: page, ref: ref);
popularManga = await Comick()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***************/
@ -32,7 +33,7 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
/**************/
if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
popularManga = await MangaThemeSia()
.getPopularManga(source: source, page: page, ref: ref);
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
@ -40,7 +41,7 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
/***********/
if (source == "mangakawaii") {
popularManga = await MangaKawaii()
.getPopularManga(source: source, page: page, ref: ref);
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
@ -48,38 +49,46 @@ Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
/***********/
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
popularManga =
await Mmrcms().getPopularManga(source: source, page: page, ref: ref);
popularManga = await Mmrcms()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*mangahere*/
/***********/
else if (source == "mangahere") {
popularManga =
await Mangahere().getPopularManga(source: source, page: page, ref: ref);
popularManga = await Mangahere()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*japscan*/
/***********/
else if (source == "japscan") {
popularManga =
await Japscan().getPopularManga(source: source, page: page, ref: ref);
popularManga = await Japscan()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*heancms*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.heancms) {
popularManga =
await HeanCms().getPopularManga(source: source, page: page, ref: ref);
popularManga = await HeanCms()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*madara*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.madara) {
popularManga =
await Madara().getPopularManga(source: source, page: page, ref: ref);
popularManga = await Madara()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
/***********/
/*mangadex*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.mangadex) {
popularManga = await MangaDex()
.getPopularManga(source: source, page: page, ref: ref, lang: lang);
}
return popularManga!;
}

View file

@ -6,7 +6,7 @@ part of 'get_popular_manga.dart';
// RiverpodGenerator
// **************************************************************************
String _$getPopularMangaHash() => r'e973741f7105e38032412a7ae160003565779463';
String _$getPopularMangaHash() => r'4fe87d57b93957bbc848b9b814dd3c9aa94b89c5';
/// Copied from Dart SDK
class _SystemHash {
@ -44,10 +44,12 @@ class GetPopularMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
GetPopularMangaProvider call({
required String source,
required int page,
required String lang,
}) {
return GetPopularMangaProvider(
source: source,
page: page,
lang: lang,
);
}
@ -58,6 +60,7 @@ class GetPopularMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
return call(
source: provider.source,
page: provider.page,
lang: provider.lang,
);
}
@ -83,11 +86,13 @@ class GetPopularMangaProvider
GetPopularMangaProvider({
required this.source,
required this.page,
required this.lang,
}) : super.internal(
(ref) => getPopularManga(
ref,
source: source,
page: page,
lang: lang,
),
from: getPopularMangaProvider,
name: r'getPopularMangaProvider',
@ -102,12 +107,14 @@ class GetPopularMangaProvider
final String source;
final int page;
final String lang;
@override
bool operator ==(Object other) {
return other is GetPopularMangaProvider &&
other.source == source &&
other.page == page;
other.page == page &&
other.lang == lang;
}
@override
@ -115,6 +122,7 @@ class GetPopularMangaProvider
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, source.hashCode);
hash = _SystemHash.combine(hash, page.hashCode);
hash = _SystemHash.combine(hash, lang.hashCode);
return _SystemHash.finish(hash);
}

View file

@ -12,6 +12,7 @@ Future<dynamic> httpGet(HttpGetRef ref,
{required String url,
required String source,
required bool resDom,
Map<String, String>? headers,
bool useUserAgent = false}) async {
bool isCloudflaree = isCloudflare(source);
if (resDom) {
@ -22,7 +23,8 @@ Future<dynamic> httpGet(HttpGetRef ref,
.future);
} else {
dom = await httpResToDom(
url: url, headers: ref.watch(headersProvider(source: source)));
url: url,
headers: headers ?? ref.watch(headersProvider(source: source)));
}
return dom;
} else {
@ -34,7 +36,7 @@ Future<dynamic> httpGet(HttpGetRef ref,
} else {
try {
final response = await http.get(Uri.parse(url),
headers: ref.watch(headersProvider(source: source)));
headers: headers ?? ref.watch(headersProvider(source: source)));
resHtml = response.body;
} catch (e) {
rethrow;

View file

@ -6,7 +6,7 @@ part of 'http_service.dart';
// RiverpodGenerator
// **************************************************************************
String _$httpGetHash() => r'57b50256bd7577a4d795cf74f9429d3a4434792f';
String _$httpGetHash() => r'115d7fdde9392d32055ddefe661731c37b2b584e';
/// Copied from Dart SDK
class _SystemHash {
@ -45,12 +45,14 @@ class HttpGetFamily extends Family<AsyncValue<dynamic>> {
required String url,
required String source,
required bool resDom,
Map<String, String>? headers,
bool useUserAgent = false,
}) {
return HttpGetProvider(
url: url,
source: source,
resDom: resDom,
headers: headers,
useUserAgent: useUserAgent,
);
}
@ -63,6 +65,7 @@ class HttpGetFamily extends Family<AsyncValue<dynamic>> {
url: provider.url,
source: provider.source,
resDom: provider.resDom,
headers: provider.headers,
useUserAgent: provider.useUserAgent,
);
}
@ -89,6 +92,7 @@ class HttpGetProvider extends AutoDisposeFutureProvider<dynamic> {
required this.url,
required this.source,
required this.resDom,
this.headers,
this.useUserAgent = false,
}) : super.internal(
(ref) => httpGet(
@ -96,6 +100,7 @@ class HttpGetProvider extends AutoDisposeFutureProvider<dynamic> {
url: url,
source: source,
resDom: resDom,
headers: headers,
useUserAgent: useUserAgent,
),
from: httpGetProvider,
@ -111,6 +116,7 @@ class HttpGetProvider extends AutoDisposeFutureProvider<dynamic> {
final String url;
final String source;
final bool resDom;
final Map<String, String>? headers;
final bool useUserAgent;
@override
@ -119,6 +125,7 @@ class HttpGetProvider extends AutoDisposeFutureProvider<dynamic> {
other.url == url &&
other.source == source &&
other.resDom == resDom &&
other.headers == headers &&
other.useUserAgent == useUserAgent;
}
@ -128,6 +135,7 @@ class HttpGetProvider extends AutoDisposeFutureProvider<dynamic> {
hash = _SystemHash.combine(hash, url.hashCode);
hash = _SystemHash.combine(hash, source.hashCode);
hash = _SystemHash.combine(hash, resDom.hashCode);
hash = _SystemHash.combine(hash, headers.hashCode);
hash = _SystemHash.combine(hash, useUserAgent.hashCode);
return _SystemHash.finish(hash);

View file

@ -3,6 +3,7 @@ import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
import 'package:mangayomi/sources/src/all/mangadex/src/mangadex.dart';
import 'package:mangayomi/sources/src/en/mangahere/src/mangahere.dart';
import 'package:mangayomi/sources/src/fr/japscan/src/japscan.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/src/mangakawaii.dart';
@ -13,8 +14,12 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'search_manga.g.dart';
@riverpod
Future<List<GetManga?>> searchManga(SearchMangaRef ref,
{required String source, required String query}) async {
Future<List<GetManga?>> searchManga(
SearchMangaRef ref, {
required String source,
required String query,
required String lang,
}) async {
List<GetManga?>? manga;
source = source.toLowerCase();
@ -23,7 +28,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/********/
if (getMangaTypeSource(source) == TypeSource.comick) {
manga = await Comick().searchManga(source: source, query: query, ref: ref);
manga = await Comick()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***************/
@ -32,7 +38,7 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
else if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
manga = await MangaThemeSia()
.searchManga(source: source, query: query, ref: ref);
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
@ -40,8 +46,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/***********/
else if (source == "mangakawaii") {
manga =
await MangaKawaii().searchManga(source: source, query: query, ref: ref);
manga = await MangaKawaii()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
@ -49,7 +55,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/***********/
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
manga = await Mmrcms().searchManga(source: source, query: query, ref: ref);
manga = await Mmrcms()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
@ -57,8 +64,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/***********/
else if (source == "mangahere") {
manga =
await Mangahere().searchManga(source: source, query: query, ref: ref);
manga = await Mangahere()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
@ -66,7 +73,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/***********/
else if (source == "japscan") {
manga = await Japscan().searchManga(source: source, query: query, ref: ref);
manga = await Japscan()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
@ -74,7 +82,8 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/***********/
else if (getMangaTypeSource(source) == TypeSource.heancms) {
manga = await HeanCms().searchManga(source: source, query: query, ref: ref);
manga = await HeanCms()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
@ -82,8 +91,17 @@ Future<List<GetManga?>> searchManga(SearchMangaRef ref,
/***********/
else if (getMangaTypeSource(source) == TypeSource.madara) {
manga = await Madara().searchManga(source: source, query: query, ref: ref);
manga = await Madara()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
/***********/
/*mangadex*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.mangadex) {
manga = await MangaDex()
.searchManga(source: source, query: query, ref: ref, lang: lang);
}
return manga!;
}

View file

@ -6,7 +6,7 @@ part of 'search_manga.dart';
// RiverpodGenerator
// **************************************************************************
String _$searchMangaHash() => r'5f2a70ca38af7448f546f70db81cbe55a79a5fba';
String _$searchMangaHash() => r'0448881ce3785ac0c670a87914590008ae19fdd5';
/// Copied from Dart SDK
class _SystemHash {
@ -44,10 +44,12 @@ class SearchMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
SearchMangaProvider call({
required String source,
required String query,
required String lang,
}) {
return SearchMangaProvider(
source: source,
query: query,
lang: lang,
);
}
@ -58,6 +60,7 @@ class SearchMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
return call(
source: provider.source,
query: provider.query,
lang: provider.lang,
);
}
@ -82,11 +85,13 @@ class SearchMangaProvider extends AutoDisposeFutureProvider<List<GetManga?>> {
SearchMangaProvider({
required this.source,
required this.query,
required this.lang,
}) : super.internal(
(ref) => searchManga(
ref,
source: source,
query: query,
lang: lang,
),
from: searchMangaProvider,
name: r'searchMangaProvider',
@ -101,12 +106,14 @@ class SearchMangaProvider extends AutoDisposeFutureProvider<List<GetManga?>> {
final String source;
final String query;
final String lang;
@override
bool operator ==(Object other) {
return other is SearchMangaProvider &&
other.source == source &&
other.query == query;
other.query == query &&
other.lang == lang;
}
@override
@ -114,6 +121,7 @@ class SearchMangaProvider extends AutoDisposeFutureProvider<List<GetManga?>> {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, source.hashCode);
hash = _SystemHash.combine(hash, query.hashCode);
hash = _SystemHash.combine(hash, lang.hashCode);
return _SystemHash.finish(hash);
}

View file

@ -95,6 +95,7 @@ class HeanCms extends MangaYomiServices {
Future<List<GetManga>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
var request = http.Request(
'POST', Uri.parse('${getMangaAPIUrl(source)}series/querysearch'));
@ -136,6 +137,7 @@ class HeanCms extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
var request = http.Request(
'POST', Uri.parse('${getMangaAPIUrl(source)}series/search'));
@ -172,6 +174,7 @@ class HeanCms extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
var request = http.Request(
'POST', Uri.parse('${getMangaAPIUrl(source)}series/querysearch'));

View file

@ -208,6 +208,7 @@ class Madara extends MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
String? html;
html = await ref.watch(httpGetProvider(
@ -246,6 +247,7 @@ class Madara extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final html = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/?s=$query&post_type=wp-manga',
@ -263,6 +265,7 @@ class Madara extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
String? html;
html = await ref.watch(httpGetProvider(

View file

@ -144,6 +144,7 @@ class MangaThemeSia extends MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
source = source.toLowerCase();
final dom = await ref.watch(httpGetProvider(
@ -194,6 +195,7 @@ class MangaThemeSia extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/?s=${query.trim()}',
@ -282,6 +284,7 @@ class MangaThemeSia extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
source = source.toLowerCase();
final dom = await ref.watch(httpGetProvider(

View file

@ -109,6 +109,7 @@ class Mmrcms extends MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url:
@ -138,6 +139,7 @@ class Mmrcms extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final response = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/search?query=${query.trim()}',
@ -197,6 +199,7 @@ class Mmrcms extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/latest-release?page=$page',

View file

@ -66,10 +66,12 @@ abstract class MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref});
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref});
Future<GetManga?> getMangaDetail(
{required GetManga manga,
@ -81,6 +83,7 @@ abstract class MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref});
}

View file

@ -1,6 +1,7 @@
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/sources/multisrc/heancms/heancms_source_list.dart';
import 'package:mangayomi/sources/src/all/comick/comick_source_list.dart';
import 'package:mangayomi/sources/src/all/mangadex/mangadex_source_list.dart';
import 'package:mangayomi/sources/src/en/mangahere/mangahere_source.dart';
import 'package:mangayomi/sources/src/fr/japscan/japscan_source.dart';
import 'package:mangayomi/sources/multisrc/mangathemesia/mangathemesia_source_list.dart';
@ -16,5 +17,6 @@ List<Source> _sourcesList = [
...mmrcmsSourcesList,
japscanSource,
...heanCmsSourcesList,
...madaraSourcesList
...madaraSourcesList,
...mangaDexSourcesList
];

View file

@ -15,6 +15,7 @@ class Comick extends MangaYomiServices {
@override
Future<List<GetManga?>> getPopularManga(
{required String source,
required String lang,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
source = source.toLowerCase();
@ -100,6 +101,7 @@ class Comick extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final response = await ref.watch(httpGetProvider(
url:
@ -141,11 +143,11 @@ class Comick extends MangaYomiServices {
return pageUrls;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
source = source.toLowerCase();
final response = await ref.watch(httpGetProvider(

View file

@ -0,0 +1,179 @@
import 'package:mangayomi/models/source.dart';
const logoUrl = '';
const apiUrl = 'https://api.mangadex.org';
const baseUrl = 'https://mangadex.org';
const isNsfw = true;
List<Source> get mangaDexSourcesList => _mangaDexSourcesList;
List<Source> _mangaDexSourcesList = [
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'en',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'ar',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'pt',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'pt-br',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'it',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'ru',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'es',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'es-419',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'id',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'hi',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'de',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'ja',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'tr',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'pl',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'zh',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'zh-hk',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
Source(
sourceName: 'MangaDex',
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'fr',
typeSource: TypeSource.mangadex,
logoUrl: logoUrl,
dateFormat: "yyyy-MM-dd'T'HH:mm:ss+SSS",
isNsfw: isNsfw,
dateFormatLocale: 'en_Us'),
];

View file

@ -0,0 +1,52 @@
class Aggregate {
String? result;
Map<String, AggregateVolumes>? volumes;
Aggregate({this.result, this.volumes});
Aggregate.fromJson(Map<String, dynamic> json) {
result = json['result'];
if (json['volumes'] is List<dynamic>) {
volumes = (json['volumes'] as List<dynamic>).asMap().map((key, value) =>
MapEntry(key.toString(),
AggregateVolumes.fromJson(value as Map<String, dynamic>)));
} else {
volumes = (json['volumes'] as Map<String, dynamic>?)?.map((key, value) =>
MapEntry(
key, AggregateVolumes.fromJson(value as Map<String, dynamic>)));
}
}
}
class AggregateVolumes {
String? volume;
String? count;
Map<String, AggregateChapter>? chapters;
AggregateVolumes({this.volume, this.chapters, this.count});
AggregateVolumes.fromJson(Map<String, dynamic> json) {
volume = json['volume'];
count = json['count'].toString();
if (json['chapters'] is List<dynamic>) {
chapters = (json['chapters'] as List<dynamic>).asMap().map((key, value) =>
MapEntry(key.toString(),
AggregateChapter.fromJson(value as Map<String, dynamic>)));
} else {
chapters = (json['chapters'] as Map<String, dynamic>?)?.map(
(key, value) => MapEntry(
key, AggregateChapter.fromJson(value as Map<String, dynamic>)));
}
}
}
class AggregateChapter {
String? chapter;
String? count;
AggregateChapter({this.chapter, this.count});
AggregateChapter.fromJson(Map<String, dynamic> json) {
chapter = json['chapter'];
count = json['count'].toString();
}
}

View file

@ -0,0 +1,108 @@
class ChapterMDX {
String? result;
String? response;
List<Data>? data;
int? limit;
int? offset;
int? total;
ChapterMDX(
{this.result,
this.response,
this.data,
this.limit,
this.offset,
this.total});
ChapterMDX.fromJson(Map<String, dynamic> json) {
result = json['result'];
response = json['response'];
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {
data!.add(Data.fromJson(v));
});
}
limit = json['limit'];
offset = json['offset'];
total = json['total'];
}
}
class Data {
String? id;
String? type;
Attributes? attributes;
List<Relationships>? relationships;
Data({this.id, this.type, this.attributes, this.relationships});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? Attributes.fromJson(json['attributes'])
: null;
if (json['relationships'] != null) {
relationships = <Relationships>[];
json['relationships'].forEach((v) {
relationships!.add(Relationships.fromJson(v));
});
}
}
}
class Attributes {
String? volume;
String? chapter;
String? title;
String? translatedLanguage;
String? publishAt;
String? readableAt;
String? createdAt;
String? updatedAt;
int? pages;
int? version;
Attributes(
{this.volume,
this.chapter,
this.title,
this.translatedLanguage,
this.publishAt,
this.readableAt,
this.createdAt,
this.updatedAt,
this.pages,
this.version});
Attributes.fromJson(Map<String, dynamic> json) {
volume = json['volume'];
chapter = json['chapter'];
title = json['title'];
translatedLanguage = json['translatedLanguage'];
publishAt = json['publishAt'];
readableAt = json['readableAt'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
pages = json['pages'];
version = json['version'];
}
}
class Relationships {
String? id;
String? type;
Relationships({
this.id,
this.type,
});
Relationships.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
}
}

View file

@ -0,0 +1,140 @@
class CoverAA {
String? result;
String? response;
List<CoverData>? data;
int? limit;
int? offset;
int? total;
CoverAA(
{this.result,
this.response,
this.data,
this.limit,
this.offset,
this.total});
CoverAA.fromJson(Map<String, dynamic> json) {
result = json['result'];
response = json['response'];
if (json['data'] != null) {
data = <CoverData>[];
json['data'].forEach((v) {
data!.add(CoverData.fromJson(v));
});
}
limit = json['limit'];
offset = json['offset'];
total = json['total'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['result'] = result;
data['response'] = response;
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
data['limit'] = limit;
data['offset'] = offset;
data['total'] = total;
return data;
}
}
class CoverData {
String? id;
String? type;
Attributes? attributes;
List<Relationships>? relationships;
CoverData({this.id, this.type, this.attributes, this.relationships});
CoverData.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? Attributes.fromJson(json['attributes'])
: null;
if (json['relationships'] != null) {
relationships = <Relationships>[];
json['relationships'].forEach((v) {
relationships!.add(Relationships.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['type'] = type;
if (attributes != null) {
data['attributes'] = attributes!.toJson();
}
if (relationships != null) {
data['relationships'] =
relationships!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Attributes {
String? description;
String? volume;
String? fileName;
String? locale;
String? createdAt;
String? updatedAt;
int? version;
Attributes(
{this.description,
this.volume,
this.fileName,
this.locale,
this.createdAt,
this.updatedAt,
this.version});
Attributes.fromJson(Map<String, dynamic> json) {
description = json['description'];
volume = json['volume'];
fileName = json['fileName'];
locale = json['locale'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
version = json['version'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['description'] = description;
data['volume'] = volume;
data['fileName'] = fileName;
data['locale'] = locale;
data['createdAt'] = createdAt;
data['updatedAt'] = updatedAt;
data['version'] = version;
return data;
}
}
class Relationships {
String? id;
String? type;
Relationships({this.id, this.type});
Relationships.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['type'] = type;
return data;
}
}

View file

@ -0,0 +1,28 @@
class GetChapterUrl {
String? result;
String? baseUrl;
Chapter? chapter;
GetChapterUrl({this.result, this.baseUrl, this.chapter});
GetChapterUrl.fromJson(Map<String, dynamic> json) {
result = json['result'];
baseUrl = json['baseUrl'];
chapter =
json['chapter'] != null ? Chapter.fromJson(json['chapter']) : null;
}
}
class Chapter {
String? hash;
List<String>? data;
List<String>? dataSaver;
Chapter({this.hash, this.data, this.dataSaver});
Chapter.fromJson(Map<String, dynamic> json) {
hash = json['hash'];
data = json['data'].cast<String>();
dataSaver = json['dataSaver'].cast<String>();
}
}

View file

@ -0,0 +1,330 @@
class MangaDexDto {
String? result;
String? response;
List<Data>? data;
int? limit;
int? offset;
int? total;
MangaDexDto(
{this.result,
this.response,
this.data,
this.limit,
this.offset,
this.total});
MangaDexDto.fromJson(Map<String, dynamic> json) {
result = json['result'];
response = json['response'];
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {
data!.add(Data.fromJson(v));
});
}
limit = json['limit'];
offset = json['offset'];
total = json['total'];
}
}
class Data {
String? id;
String? type;
Attributes? attributes;
List<Relationships>? relationships;
Data({this.id, this.type, this.attributes, this.relationships});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? Attributes.fromJson(json['attributes'])
: null;
if (json['relationships'] != null) {
relationships = <Relationships>[];
json['relationships'].forEach((v) {
relationships!.add(Relationships.fromJson(v));
});
}
}
}
class Attributes {
Map<String, dynamic>? title;
List<dynamic>? altTitles;
Description? description;
bool? isLocked;
Links? links;
String? originalLanguage;
String? lastVolume;
String? lastChapter;
String? publicationDemographic;
String? status;
int? year;
String? contentRating;
List<Tags>? tags;
String? state;
bool? chapterNumbersResetOnNewVolume;
String? createdAt;
String? updatedAt;
int? version;
List<String>? availableTranslatedLanguages;
String? latestUploadedChapter;
Attributes(
{this.title,
this.altTitles,
this.description,
this.isLocked,
this.links,
this.originalLanguage,
this.lastVolume,
this.lastChapter,
this.publicationDemographic,
this.status,
this.year,
this.contentRating,
this.tags,
this.state,
this.chapterNumbersResetOnNewVolume,
this.createdAt,
this.updatedAt,
this.version,
this.availableTranslatedLanguages,
this.latestUploadedChapter});
Attributes.fromJson(Map<String, dynamic> json) {
title = json['title'] as Map<String, dynamic>;
if (json['altTitles'] != null) {
altTitles = json['altTitles'];
}
description = json['description'] != null
? Description.fromJson(json['description'])
: null;
isLocked = json['isLocked'];
links = json['links'] != null ? Links.fromJson(json['links']) : null;
originalLanguage = json['originalLanguage'];
lastVolume = json['lastVolume'];
lastChapter = json['lastChapter'];
publicationDemographic = json['publicationDemographic'];
status = json['status'];
year = json['year'];
contentRating = json['contentRating'];
if (json['tags'] != null) {
tags = <Tags>[];
json['tags'].forEach((v) {
tags!.add(Tags.fromJson(v));
});
}
state = json['state'];
chapterNumbersResetOnNewVolume = json['chapterNumbersResetOnNewVolume'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
version = json['version'];
availableTranslatedLanguages =
json['availableTranslatedLanguages'].cast<String>();
latestUploadedChapter = json['latestUploadedChapter'];
}
}
class Description {
String? en;
String? fr;
String? pt;
String? ptBr;
String? zhHk;
String? ru;
String? es;
String? ja;
String? tr;
String? uk;
String? esLa;
String? ko;
String? de;
String? id;
String? it;
String? pl;
String? th;
String? zh;
String? cs;
Description(
{this.en,
this.fr,
this.pt,
this.ptBr,
this.zhHk,
this.ru,
this.es,
this.ja,
this.tr,
this.uk,
this.esLa,
this.ko,
this.de,
this.id,
this.it,
this.pl,
this.th,
this.zh,
this.cs});
Description.fromJson(Map<String, dynamic> json) {
en = json['en'];
fr = json['fr'];
pt = json['pt'];
ptBr = json['pt-br'];
zhHk = json['zh-hk'];
ru = json['ru'];
es = json['es'];
ja = json['ja'];
tr = json['tr'];
uk = json['uk'];
esLa = json['es-la'];
ko = json['ko'];
de = json['de'];
id = json['id'];
it = json['it'];
pl = json['pl'];
th = json['th'];
zh = json['zh'];
cs = json['cs'];
}
}
class Links {
String? al;
String? mu;
String? amz;
String? mal;
String? engtl;
String? kt;
String? cdj;
String? ebj;
String? raw;
String? ap;
String? bw;
String? nu;
Links(
{this.al,
this.mu,
this.amz,
this.mal,
this.engtl,
this.kt,
this.cdj,
this.ebj,
this.raw,
this.ap,
this.bw,
this.nu});
Links.fromJson(Map<String, dynamic> json) {
al = json['al'];
mu = json['mu'];
amz = json['amz'];
mal = json['mal'];
engtl = json['engtl'];
kt = json['kt'];
cdj = json['cdj'];
ebj = json['ebj'];
raw = json['raw'];
ap = json['ap'];
bw = json['bw'];
nu = json['nu'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['al'] = al;
data['mu'] = mu;
data['amz'] = amz;
data['mal'] = mal;
data['engtl'] = engtl;
data['kt'] = kt;
data['cdj'] = cdj;
data['ebj'] = ebj;
data['raw'] = raw;
data['ap'] = ap;
data['bw'] = bw;
data['nu'] = nu;
return data;
}
}
class Tags {
TagAttributes? attributes;
Tags({
this.attributes,
});
Tags.fromJson(Map<String, dynamic> json) {
attributes = json['attributes'] != null
? TagAttributes.fromJson(json['attributes'])
: null;
}
}
class TagAttributes {
String? group;
TagAttributes({this.group});
TagAttributes.fromJson(Map<String, dynamic> json) {
group = json['group'];
}
}
class Relationships {
String? id;
String? type;
RAttributes? attributes;
String? related;
Relationships({this.id, this.type, this.attributes, this.related});
Relationships.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? RAttributes.fromJson(json['attributes'])
: null;
related = json['related'];
}
}
class RAttributes {
String? description;
String? volume;
String? fileName;
String? locale;
String? createdAt;
String? updatedAt;
int? version;
RAttributes(
{this.description,
this.volume,
this.fileName,
this.locale,
this.createdAt,
this.updatedAt,
this.version});
RAttributes.fromJson(Map<String, dynamic> json) {
description = json['description'];
volume = json['volume'];
fileName = json['fileName'];
locale = json['locale'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
version = json['version'];
}
}

View file

@ -0,0 +1,209 @@
class MDXDetail {
String? result;
String? response;
Dataa? data;
MDXDetail({this.result, this.response, this.data});
MDXDetail.fromJson(Map<String, dynamic> json) {
result = json['result'];
response = json['response'];
data = json['data'] != null ? Dataa.fromJson(json['data']) : null;
}
}
class Dataa {
String? id;
String? type;
Attributes? attributes;
List<Relationships>? relationships;
Dataa({this.id, this.type, this.attributes, this.relationships});
Dataa.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? Attributes.fromJson(json['attributes'])
: null;
if (json['relationships'] != null) {
relationships = <Relationships>[];
json['relationships'].forEach((v) {
relationships!.add(Relationships.fromJson(v));
});
}
}
}
class Attributes {
Title? title;
Map<String, dynamic>? description;
bool? isLocked;
String? originalLanguage;
String? lastVolume;
String? lastChapter;
String? publicationDemographic;
String? status;
int? year;
String? contentRating;
List<Tags>? tags;
String? state;
bool? chapterNumbersResetOnNewVolume;
String? createdAt;
String? updatedAt;
int? version;
List<String>? availableTranslatedLanguages;
String? latestUploadedChapter;
Attributes(
{this.title,
this.description,
this.isLocked,
this.originalLanguage,
this.lastVolume,
this.lastChapter,
this.publicationDemographic,
this.status,
this.year,
this.contentRating,
this.tags,
this.state,
this.chapterNumbersResetOnNewVolume,
this.createdAt,
this.updatedAt,
this.version,
this.availableTranslatedLanguages,
this.latestUploadedChapter});
Attributes.fromJson(Map<String, dynamic> json) {
title = json['title'] != null ? Title.fromJson(json['title']) : null;
description = json['description'];
isLocked = json['isLocked'];
originalLanguage = json['originalLanguage'];
lastVolume = json['lastVolume'];
lastChapter = json['lastChapter'];
publicationDemographic = json['publicationDemographic'];
status = json['status'];
year = json['year'];
contentRating = json['contentRating'];
if (json['tags'] != null) {
tags = <Tags>[];
json['tags'].forEach((v) {
tags!.add(Tags.fromJson(v));
});
}
state = json['state'];
chapterNumbersResetOnNewVolume = json['chapterNumbersResetOnNewVolume'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
version = json['version'];
availableTranslatedLanguages =
json['availableTranslatedLanguages'].cast<String>();
latestUploadedChapter = json['latestUploadedChapter'];
}
}
class Title {
String? en;
Title({this.en});
Title.fromJson(Map<String, dynamic> json) {
en = json['en'];
}
}
class Tags {
String? id;
String? type;
TAttributes? attributes;
Tags({this.id, this.type, this.attributes});
Tags.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? TAttributes.fromJson(json['attributes'])
: null;
}
}
class TAttributes {
Title? name;
Map<String, dynamic>? description;
String? group;
int? version;
TAttributes({this.name, this.description, this.group, this.version});
TAttributes.fromJson(Map<String, dynamic> json) {
name = json['name'] != null ? Title.fromJson(json['name']) : null;
description = json['description'];
group = json['group'];
version = json['version'];
}
}
class Relationships {
String? id;
String? type;
RAttributes? attributes;
String? related;
Relationships({this.id, this.type, this.attributes, this.related});
Relationships.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
attributes = json['attributes'] != null
? RAttributes.fromJson(json['attributes'])
: null;
related = json['related'];
}
}
class RAttributes {
String? name;
Title? biography;
String? twitter;
String? createdAt;
String? updatedAt;
int? version;
String? description;
String? volume;
String? fileName;
String? locale;
RAttributes(
{this.name,
this.biography,
this.twitter,
this.createdAt,
this.updatedAt,
this.version,
this.description,
this.volume,
this.fileName,
this.locale});
RAttributes.fromJson(Map<String, dynamic> json) {
name = json['name'];
biography =
json['biography'] != null ? Title.fromJson(json['biography']) : null;
twitter = json['twitter'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
version = json['version'];
description = json['description'];
volume = json['volume'];
fileName = json['fileName'];
locale = json['locale'];
}
}

View file

@ -0,0 +1,299 @@
import 'dart:convert';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/services/http_service/http_service.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/chapter.dart' as mdx;
import 'package:mangayomi/sources/src/all/mangadex/model/cover.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/aggregate.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/get_chapter_url.dart'
as get_chap_url;
import 'package:mangayomi/sources/src/all/mangadex/model/manga.dart'
as manga_dx;
import 'package:mangayomi/sources/src/all/mangadex/model/mdx_detail.dart'
as mdx_detail;
import 'package:mangayomi/sources/src/all/mangadex/src/utils/utils.dart';
import 'package:mangayomi/sources/utils/utils.dart';
class MangaDex extends MangaYomiServices {
@override
Future<List<String>> getChapterUrl(
{required Chapter chapter,
required AutoDisposeFutureProviderRef ref}) async {
String chapterId = chapter.url!.split('/').last;
String source = chapter.manga.value!.source!;
final response = await ref.watch(httpGetProvider(
url: '${getMangaAPIUrl(source)}/at-home/server/$chapterId',
source: source,
resDom: false)
.future) as String?;
final result = jsonDecode(response!) as Map<String, dynamic>;
final atHome = get_chap_url.GetChapterUrl.fromJson(result);
final host = atHome.baseUrl;
final hash = atHome.chapter!.hash!;
List<String> pageSuffix = [];
for (var data in atHome.chapter!.data!) {
pageSuffix.add("/data/$hash/$data");
}
for (var url in pageSuffix) {
pageUrls.add("$host$url");
}
return pageUrls;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/chapter?limit=20&offset=${(20 * (page - 1))}&translatedLanguage[]=$lang&includeFutureUpdates=0${getMDXContentRating()}&order[publishAt]=desc&includeFuturePublishAt=0&includeEmptyPages=0',
source: source,
resDom: false,
).future) as String?;
final result = jsonDecode(response!) as Map<String, dynamic>;
final chapterList = mdx.ChapterMDX.fromJson(result);
List<String> mangaIds = [];
for (var element in chapterList.data!) {
for (var el in element.relationships!) {
mangaIds.add(el.id!);
}
}
mangaIds = mangaIds.toSet().toList();
String manga = "";
for (var id in mangaIds) {
manga = "$manga&ids[]=$id";
}
final mangaResponse = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/manga?includes[]=cover_art&limit=${mangaIds.length}${getMDXContentRating()}$manga',
source: source,
resDom: false,
).future) as String?;
final res = jsonDecode(mangaResponse!) as Map<String, dynamic>;
final resultt = manga_dx.MangaDexDto.fromJson(res);
final firstVolumeCovers =
await fetchFirstVolumeCovers(resultt.data, source, ref);
for (var da in resultt.data!) {
url.add("/manga/${da.id}");
name.add(findTitle(da.attributes!.altTitles, da.attributes!.title, lang));
image.add(
"https://uploads.mangadex.org/covers/${da.id}/${getFileName(da.id!, resultt.data, firstVolumeCovers)}");
}
return mangaRes();
}
@override
Future<GetManga?> getMangaDetail(
{required GetManga manga,
required String lang,
required String source,
required AutoDisposeFutureProviderRef ref}) async {
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}${manga.url}?includes[]=cover_art&includes[]=author&includes[]=artist',
source: source,
resDom: false,
).future) as String?;
final res = jsonDecode(response!) as Map<String, dynamic>;
final result = mdx_detail.MDXDetail.fromJson(res);
final aggregate = await fetchSimpleChapterList(result, lang, source, ref);
List<String> authors = [];
for (var element in result.data!.relationships!) {
if (element.attributes != null) {
authors.add(element.attributes!.name ?? "");
}
}
final attr = result.data!.attributes!;
author = authors.join(", ");
Map<String, dynamic>? descrip = attr.description;
description = descrip![lang] ?? descrip["en"] ?? "";
for (var element in attr.tags!) {
if (element.attributes != null) {
genre.add(element.attributes!.name!.en!);
}
}
genre = [
...genre,
attr.publicationDemographic ?? "",
attr.contentRating != null && attr.contentRating!.toLowerCase() != "safe"
? "Content rating: ${attr.contentRating}"
: ""
].where((element) => element.isNotEmpty).toList();
status = getPublicationStatus(aggregate, attr);
String mangaId = manga.url!.split('/').last;
final paginatedChapterList =
await paginatedChapterListRequest(mangaId, 0, ref, source, lang);
final rres = jsonDecode(paginatedChapterList) as Map<String, dynamic>;
final chapterListResponse = mdx.ChapterMDX.fromJson(rres);
final chapterListResults = chapterListResponse.data;
var limit = chapterListResponse.limit!;
var offset = chapterListResponse.offset!;
var hasMoreResults = (limit + offset) < chapterListResponse.total!;
while (hasMoreResults) {
offset += limit;
var newRequest =
await paginatedChapterListRequest(mangaId, offset, ref, source, lang);
final rres = jsonDecode(newRequest) as Map<String, dynamic>;
var newChapterList = mdx.ChapterMDX.fromJson(rres);
chapterListResults!.addAll(newChapterList.data!);
hasMoreResults = (limit + offset) < newChapterList.total!;
}
for (var chapterData in chapterListResults!) {
List<String> chapName = [];
var chapAttr = chapterData.attributes!;
if (chapAttr.volume != null && chapAttr.volume!.isNotEmpty) {
chapName.add("Vol.${chapAttr.volume}");
}
if (chapAttr.chapter != null && chapAttr.chapter!.isNotEmpty) {
chapName.add("Ch.${chapAttr.chapter}");
}
if (chapAttr.title != null && chapAttr.title!.isNotEmpty) {
if (chapName.isNotEmpty) {
chapName.add("-");
}
chapName.add(chapAttr.title!);
}
if (chapName.isEmpty) {
chapName.add("Oneshot");
}
chapterUrl.add("/chapter/${chapterData.id}");
chapterTitle.add(chapName.join(" "));
chapterDate.add(parseDate(chapAttr.publishAt!, source));
}
return mangadetailRes(manga: manga, source: source);
}
@override
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/manga?limit=20&offset=${(20 * (page - 1))}&availableTranslatedLanguage[]=$lang&includes[]=cover_art${getMDXContentRating()}&order[followedCount]=desc',
source: source,
resDom: false,
).future) as String?;
final res = jsonDecode(response!) as Map<String, dynamic>;
final result = manga_dx.MangaDexDto.fromJson(res);
final firstVolumeCovers =
await fetchFirstVolumeCovers(result.data, source, ref);
for (var da in result.data!) {
url.add("/manga/${da.id}");
name.add(findTitle(da.attributes!.altTitles, da.attributes!.title, lang));
image.add(
"https://uploads.mangadex.org/covers/${da.id}/${getFileName(da.id!, result.data, firstVolumeCovers)}");
}
return mangaRes();
}
@override
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/manga?includes[]=cover_art&offset=0&limit=20&title=${query.toLowerCase().trim()}${getMDXContentRating()}&order[followedCount]=desc&availableTranslatedLanguage[]=$lang',
source: source,
resDom: false,
).future) as String?;
final res = jsonDecode(response!) as Map<String, dynamic>;
final resultt = manga_dx.MangaDexDto.fromJson(res);
final firstVolumeCovers =
await fetchFirstVolumeCovers(resultt.data, source, ref);
for (var da in resultt.data!) {
url.add("/manga/${da.id}");
name.add(findTitle(da.attributes!.altTitles, da.attributes!.title, lang));
image.add(
"https://uploads.mangadex.org/covers/${da.id}/${getFileName(da.id!, resultt.data, firstVolumeCovers)}");
}
return mangaRes();
}
Future<List<CoverData>?> fetchFirstVolumeCovers(List<manga_dx.Data>? data,
String source, AutoDisposeFutureProviderRef ref) async {
List<String> mangaIds = [];
List<String> locales = [];
for (var element in data!) {
final attributes = element.attributes;
if (attributes!.originalLanguage != null &&
attributes.originalLanguage!.isNotEmpty) {
mangaIds.add(element.id!);
locales.add(attributes.originalLanguage!);
}
}
int limit = (mangaIds.length * locales.length);
if (limit > 100) {
limit = 100;
}
String manga = "";
for (var id in mangaIds) {
manga = "$manga&manga[]=$id";
}
String locale = "";
for (var loc in locales.toSet()) {
locale = "$locale&locales[]=$loc";
}
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/cover?order[volume]=asc&limit=$limit&offset=0$manga$locale',
source: source,
resDom: false,
).future) as String?;
final res = jsonDecode(response!) as Map<String, dynamic>;
final result = CoverAA.fromJson(res).data;
result!.sort(
(a, b) => a.relationships!.firstOrNull!.id!
.compareTo(b.relationships!.firstOrNull!.id!),
);
return result.where((element) {
return mangaIds.contains(element.relationships!.first.id);
}).toList();
}
Future<Aggregate>? fetchSimpleChapterList(mdx_detail.MDXDetail? data,
String lang, String source, AutoDisposeFutureProviderRef ref) async {
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/manga/${data!.data!.id}/aggregate?translatedLanguage[]=$lang',
source: source,
resDom: false,
).future) as String?;
final res = jsonDecode(response!) as Map<String, dynamic>;
return Aggregate.fromJson(res);
}
Future<String> paginatedChapterListRequest(String mangaId, int offset,
AutoDisposeFutureProviderRef ref, String source, String lang) async {
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/manga/$mangaId/feed?limit=500&offset=$offset&includes[]=user&includes[]=scanlation_group&order[volume]=desc&order[chapter]=desc&translatedLanguage[]=$lang&includeFuturePublishAt=0&includeEmptyPages=0&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic',
source: source,
resDom: false,
).future) as String?;
return response!;
}
}

View file

@ -0,0 +1,89 @@
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/aggregate.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/cover.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/manga.dart';
import 'package:mangayomi/sources/src/all/mangadex/model/mdx_detail.dart'
as mdx_detail;
String getMDXContentRating() {
List<String> contentRating = [
"suggestive",
"safe",
"erotica",
"pornographic"
];
String ctnRating = "";
for (var rating in contentRating) {
ctnRating = "$ctnRating&contentRating[]=$rating";
}
return ctnRating;
}
findTitle(
List<dynamic>? altTitles, Map<String, dynamic>? enTitle, String lang) {
final altTitle = altTitles!
.where((element) =>
element[lang].toString().isNotEmpty ||
element["en"].toString().isNotEmpty)
.toList();
String? altTitless = altTitle.isNotEmpty
? altTitle.firstOrNull[lang] ?? altTitle.firstOrNull["en"]
: null;
return enTitle!.values.firstOrNull ?? altTitless ?? "";
}
getFileName(String id, List<Data>? data, List<CoverData>? firstVolumeCovers) {
final mangaMap =
data!.asMap().map((key, value) => MapEntry(value.id, value.attributes));
final firstVolumeCoversF = firstVolumeCovers!
.where((element) =>
element.attributes!.locale == mangaMap[id]!.originalLanguage!)
.where((element) =>
element.attributes!.fileName != null &&
element.attributes!.fileName!.isNotEmpty)
.toList()
.asMap()
.map((key, value) =>
MapEntry(value.relationships!.first.id, value.attributes!.fileName));
final datas = data
.where((element) => element.id == id)
.toList()
.firstOrNull!
.relationships!
.firstOrNull!
.attributes;
return firstVolumeCoversF.isNotEmpty
? firstVolumeCoversF[id]
: datas != null
? datas.fileName
: "";
}
Status getPublicationStatus(Aggregate? aggregate, mdx_detail.Attributes attr) {
List<String> chaptersList = [];
for (var element in aggregate!.volumes!.values) {
for (var elem in element.chapters!.values) {
chaptersList.add(elem.chapter!);
}
}
var tempStatus = switch (attr.status) {
"ongoing" => Status.ongoing,
"cancelled" => Status.canceled,
"completed" => Status.publishingFinished,
"hiatus" => Status.onHiatus,
_ => Status.unknown,
};
var publishedOrCancelled =
tempStatus == Status.publishingFinished || tempStatus == Status.canceled;
var isOneShot = attr.tags!.any((element) => element.id == tagOneShotUuid) &&
attr.tags!.where((element) => (element.id == tagAnthologyUuid)).isEmpty;
return chaptersList.contains(attr.lastChapter) && publishedOrCancelled
? Status.completed
: isOneShot
? Status.completed
: tempStatus;
}
const tagAnthologyUuid = "51d83883-4103-437c-b4b1-731cb73d786c";
const tagOneShotUuid = "0234a31e-a729-4e28-9d6a-3f87c4966b9e";

View file

@ -118,6 +118,7 @@ class Mangahere extends MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/directory/$page.htm',
@ -151,6 +152,7 @@ class Mangahere extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url:
@ -307,6 +309,7 @@ class Mangahere extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/directory/$page.htm?latest',

View file

@ -116,6 +116,7 @@ class Japscan extends MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: "${getMangaBaseUrl(source)}/", source: source, resDom: true)
@ -145,6 +146,7 @@ class Japscan extends MangaYomiServices {
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url:
@ -262,6 +264,7 @@ class Japscan extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: "${getMangaBaseUrl(source)}/", source: source, resDom: true)

View file

@ -127,6 +127,7 @@ class MangaKawaii extends MangaYomiServices {
Future<List<GetManga?>> getPopularManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: 'https://www.mangakawaii.io/', source: source, resDom: true)
@ -143,7 +144,7 @@ class MangaKawaii extends MangaYomiServices {
.toList();
for (var ur in url) {
image.add(
"https://cdn.mangakawaii.pics/uploads$ur/cover/cover_250x350.jpg");
"https://cdn.mangakawaii.pics/uploads$ur/cover/cover_250x350.jpg");
}
}
return mangaRes();
@ -152,7 +153,7 @@ class MangaKawaii extends MangaYomiServices {
@override
Future<List<GetManga?>> searchManga(
{required String source,
required String query,
required String query, required String lang,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url:
@ -218,6 +219,7 @@ class MangaKawaii extends MangaYomiServices {
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required String lang,
required AutoDisposeFutureProviderRef ref}) {
throw UnimplementedError();
}

View file

@ -22,6 +22,17 @@ String getMangaAPIUrl(String source) {
return url;
}
String getMangaLang(String source) {
String lang = "";
for (var i = 0; i < sourcesList.length; i++) {
if (sourcesList[i].sourceName!.toLowerCase() == source.toLowerCase()) {
lang = sourcesList[i].lang!;
}
}
return lang;
}
TypeSource getMangaTypeSource(String source) {
TypeSource? typeSource;
for (var i = 0; i < sourcesList.length; i++) {

View file

@ -10,6 +10,7 @@ String getMangaStatusName(Status status) {
Status.onHiatus => "On hiatus",
Status.canceled => "Canceled",
Status.completed => "Completed",
Status.publishingFinished => "Publishing finished",
_ => "Unknown",
};
}
@ -19,7 +20,8 @@ IconData getMangaStatusIcon(Status status) {
Status.ongoing => Icons.schedule_rounded,
Status.onHiatus => Icons.pause_circle_rounded,
Status.canceled => Icons.cancel_rounded,
Status.completed => Icons.done_all_rounded,
Status.completed => Icons.done,
Status.publishingFinished => Icons.done,
_ => Icons.block_outlined,
};
}

View file

@ -14,23 +14,29 @@ Map<String, String> headers(HeadersRef ref, {String source = ""}) {
final baseUrl = getMangaBaseUrl(source);
return getMangaTypeSource(source) == TypeSource.madara
? {"Referer": "$baseUrl/"}
: switch (source) {
"mangakawaii" => {
'Referer': '$baseUrl/',
'User-Agent': userAgent,
'Accept-Language': 'fr'
},
"mangahere" => {"Referer": "$baseUrl/", "Cookie": "isAdult=1"},
"japscan" => {
'User-Agent': userAgent,
'Referer': "$baseUrl/",
"Cookie": cookie
},
"sushiscan" => {
'User-Agent': userAgent,
'Referer': "$baseUrl/",
"Cookie": cookie
},
_ => {},
};
: getMangaTypeSource(source) == TypeSource.mangadex ||
getMangaTypeSource(source) == TypeSource.comick
? {
"Referer": "$baseUrl/",
'User-Agent': "Tachiyomi $userAgent",
}
: switch (source) {
"mangakawaii" => {
'Referer': '$baseUrl/',
'User-Agent': userAgent,
'Accept-Language': 'fr'
},
"mangahere" => {"Referer": "$baseUrl/", "Cookie": "isAdult=1"},
"japscan" => {
'User-Agent': userAgent,
'Referer': "$baseUrl/",
"Cookie": cookie
},
"sushiscan" => {
'User-Agent': userAgent,
'Referer': "$baseUrl/",
"Cookie": cookie
},
_ => {},
};
}

View file

@ -6,7 +6,7 @@ part of 'headers.dart';
// RiverpodGenerator
// **************************************************************************
String _$headersHash() => r'b25fd0415020bf0585f8ecad168689935188bfad';
String _$headersHash() => r'77be1cf7504cf673ff5da1646a367e2d21f2893a';
/// Copied from Dart SDK
class _SystemHash {