mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
add source extension
This commit is contained in:
parent
da1d403c75
commit
b433d2fbc6
24 changed files with 1101 additions and 190 deletions
|
|
@ -2,4 +2,6 @@ class HiveConstant {
|
|||
static String get hiveBoxManga => "manga_box";
|
||||
static String get hiveBoxMangaInfo => "manga_box_info";
|
||||
static String get hiveBoxMangaHistory => "_manga_box_history_";
|
||||
static String get hiveBoxMangaSource => "_manga_box_source_";
|
||||
static String get hiveBoxMangaFilter => "_manga_box_filter_";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,16 +6,19 @@ import 'package:mangayomi/constant.dart';
|
|||
import 'package:mangayomi/models/manga_history.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/router/router.dart';
|
||||
import 'package:mangayomi/source/source_model.dart';
|
||||
|
||||
void main() async {
|
||||
await Hive.initFlutter();
|
||||
Hive.registerAdapter(ModelMangaAdapter());
|
||||
Hive.registerAdapter(MangaHistoryModelAdapter());
|
||||
await Hive.openBox<ModelManga>(
|
||||
HiveConstant.hiveBoxManga,
|
||||
);
|
||||
Hive.registerAdapter(SourceModelAdapter());
|
||||
Hive.registerAdapter(TypeSourceAdapter());
|
||||
await Hive.openBox<ModelManga>(HiveConstant.hiveBoxManga);
|
||||
await Hive.openBox<MangaHistoryModel>(HiveConstant.hiveBoxMangaHistory);
|
||||
await Hive.openBox<SourceModel>(HiveConstant.hiveBoxMangaSource);
|
||||
await Hive.openBox(HiveConstant.hiveBoxMangaInfo);
|
||||
await Hive.openBox(HiveConstant.hiveBoxMangaFilter);
|
||||
runApp(const ProviderScope(child: MyApp()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:hive_flutter/hive_flutter.dart';
|
|||
import 'package:mangayomi/constant.dart';
|
||||
import 'package:mangayomi/models/manga_history.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/source/source_model.dart';
|
||||
|
||||
final hiveBoxManga = Provider<Box<ModelManga>>((ref) {
|
||||
return Hive.box<ModelManga>(HiveConstant.hiveBoxManga);
|
||||
|
|
@ -14,3 +15,11 @@ final hiveBoxMangaInfo = Provider<Box>((ref) {
|
|||
final hiveBoxMangaHistory = Provider<Box<MangaHistoryModel>>((ref) {
|
||||
return Hive.box<MangaHistoryModel>(HiveConstant.hiveBoxMangaHistory);
|
||||
});
|
||||
|
||||
final hiveBoxMangaFilterProvider = Provider<Box>((ref) {
|
||||
return Hive.box(HiveConstant.hiveBoxMangaFilter);
|
||||
});
|
||||
|
||||
final hiveBoxMangaSourceProvider = Provider<Box<SourceModel>>((ref) {
|
||||
return Hive.box<SourceModel>(HiveConstant.hiveBoxMangaSource);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:mangayomi/models/manga_reader.dart';
|
|||
import 'package:mangayomi/models/manga_type.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/views/browse/browse_screen.dart';
|
||||
import 'package:mangayomi/views/browse/extension/extension_lang.dart';
|
||||
import 'package:mangayomi/views/general/general_screen.dart';
|
||||
import 'package:mangayomi/views/history/history_screen.dart';
|
||||
import 'package:mangayomi/views/library/library_screen.dart';
|
||||
|
|
@ -135,6 +136,19 @@ class AsyncRouterNotifier extends ChangeNotifier {
|
|||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: "/extensionLang",
|
||||
name: "extensionLang",
|
||||
builder: (context, state) {
|
||||
return const ExtensionsLang();
|
||||
},
|
||||
pageBuilder: (context, state) {
|
||||
return CustomTransition(
|
||||
key: state.pageKey,
|
||||
child: const ExtensionsLang(),
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,9 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
if (hiveUrl.isNotEmpty) {
|
||||
urll = hiveUrl;
|
||||
}
|
||||
|
||||
//mangahere
|
||||
/***********/
|
||||
/*mangahere*/
|
||||
/***********/
|
||||
else if (source == 'mangahere') {
|
||||
JavascriptRuntime? flutterJs;
|
||||
flutterJs = getJavascriptRuntime();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ part of 'get_manga_chapter_url.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$getMangaChapterUrlHash() =>
|
||||
r'acdd4b5eacb246441b55d1c19614032b789b0828';
|
||||
r'bd696a5ff424b0396cd67d08325945f6ac00093b';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
383
lib/source/source_list.dart
Normal file
383
lib/source/source_list.dart
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
import 'package:mangayomi/source/source_model.dart';
|
||||
|
||||
List<SourceModel> sourcesList = [
|
||||
SourceModel(
|
||||
sourceName: "MangaHere",
|
||||
url: "http://www.mangahere.cc",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.single),
|
||||
SourceModel(
|
||||
sourceName: "MangaSee",
|
||||
url: "https://mangasee123.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.single),
|
||||
SourceModel(
|
||||
sourceName: "ManngaKawaii",
|
||||
url: "https://www.mangakawaii.io",
|
||||
lang: "fr",
|
||||
typeSource: TypeSource.single),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'en',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'ar',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'pt',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'pt-br',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'it',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'ru',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'es',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'es-419',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'id',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'hi',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'de',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'ja',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'tr',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'pl',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'zh',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'zh-hk',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: 'Comick',
|
||||
url: 'https://api.comick.fun/',
|
||||
lang: 'fr',
|
||||
typeSource: TypeSource.comick),
|
||||
SourceModel(
|
||||
sourceName: "KomikLab",
|
||||
url: "https://komiklab.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "AnimatedGlitchedScans",
|
||||
url: "https://anigliscans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "ArenaScans",
|
||||
url: "https://arenascans.net",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "AzureScans",
|
||||
url: "https://azuremanga.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Boosei",
|
||||
url: "https://boosei.net",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Clayrer",
|
||||
url: "https://clayrer.net",
|
||||
lang: "es",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "CosmicScans",
|
||||
url: "https://cosmicscans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "DiskusScan",
|
||||
url: "https://diskusscan.com",
|
||||
lang: "pt-BR",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "DuniaKomik",
|
||||
url: "https://duniakomik.id",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "FlameScans",
|
||||
url: "https://flamescans.fr",
|
||||
lang: "fr",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "GremoryMangas",
|
||||
url: "https://gremorymangas.com",
|
||||
lang: "es",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "InfernalVoidScans",
|
||||
url: "https://void-scans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Kiryuu",
|
||||
url: "https://kiryuu.id",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "KomikIndo",
|
||||
url: "https://komikindo.co",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "KomikMama",
|
||||
url: "https://komikmama.co",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Komiku",
|
||||
url: "https://komiku.com",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "KumaScans (Kuma Translation)",
|
||||
url: "https://kumascans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "MangaKita",
|
||||
url: "https://mangakita.net",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "MangaTale",
|
||||
url: "https://mangatale.co",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "MangaYaro",
|
||||
url: "https://mangayaro.net",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "MangKomik",
|
||||
url: "https://mangkomik.net",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "MangásChan",
|
||||
url: "https://mangaschan.com",
|
||||
lang: "pt-BR",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "ManhwaFreak",
|
||||
url: "https://manhwafreak.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "ManhwaList",
|
||||
url: "https://manhwalist.in",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "MasterKomik",
|
||||
url: "https://masterkomik.com",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Nekomik",
|
||||
url: "https://nekomik.com",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "PhantomScans",
|
||||
url: "https://phantomscans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "PhoenixFansub",
|
||||
url: "https://phoenixfansub.com",
|
||||
lang: "es",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "PiScans",
|
||||
url: "https://piscans.in",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Rawkuma",
|
||||
url: "https://rawkuma.com/",
|
||||
lang: "ja",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "Readkomik",
|
||||
url: "https://readkomik.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "SuryaScans",
|
||||
url: "https://suryascans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "SushiScan",
|
||||
url: "https://sushiscan.ru",
|
||||
lang: "fr",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "TsundokuTraduções",
|
||||
url: "https://tsundoku.com.br",
|
||||
lang: "pt-BR",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "TukangKomik",
|
||||
url: "https://tukangkomik.id",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "WestManga",
|
||||
url: "https://westmanga.info",
|
||||
lang: "id",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
SourceModel(
|
||||
sourceName: "xCaliBRScans",
|
||||
url: "https://xcalibrscans.com",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia),
|
||||
];
|
||||
|
||||
|
||||
|
||||
// List<SourceModel> sourcesList = [
|
||||
// SourceModel(Source("MangaHere", "http://www.mangahere.cc", "en", TypeSource.single)),
|
||||
// SourceModel(Source("MangaSee", "https://mangasee123.com", "en", typeSource:TypeSource.single)),
|
||||
// SourceModel(Source(
|
||||
// "ManngaKawaii", "https://www.mangakawaii.io", "fr", typeSource:TypeSource.single)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'en', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'ar', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'pt', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'pt-br', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'it', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'ru', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'es', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'es-419', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'id', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'hi', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'de', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'ja', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'tr', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'pl', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'zh', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'zh-hk', TypeSource.comick)),
|
||||
// SourceModel(Source('Comick', 'https://api.comick.fun/', 'fr', TypeSource.comick)),
|
||||
// SourceModel(Source(
|
||||
// "KomikLab", "https://komiklab.com", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("AnimatedGlitchedScans", "https://anigliscans.com", "en",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "ArenaScans", "https://arenascans.net", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "AzureScans", "https://azuremanga.com", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("Boosei", "https://boosei.net", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("Clayrer", "https://clayrer.net", "es", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "CosmicScans", "https://cosmicscans.com", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("DiskusScan", "https://diskusscan.com", "pt-BR",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "DuniaKomik", "https://duniakomik.id", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "FlameScans", "https://flamescans.fr", "fr", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("GremoryMangas", "https://gremorymangas.com", "es",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("InfernalVoidScans", "https://void-scans.com", "en",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("Kiryuu", "https://kiryuu.id", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "KomikIndo", "https://komikindo.co", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "KomikMama", "https://komikmama.co", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("Komiku", "https://komiku.com", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("KumaScans (Kuma Translation)", "https://kumascans.com", "en",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "MangaKita", "https://mangakita.net", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "MangaTale", "https://mangatale.co", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "MangaYaro", "https://mangayaro.net", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "MangKomik", "https://mangkomik.net", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("MangásChan", "https://mangaschan.com", "pt-BR",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "ManhwaFreak", "https://manhwafreak.com", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "ManhwaList", "https://manhwalist.in", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "MasterKomik", "https://masterkomik.com", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("Nekomik", "https://nekomik.com", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("PhantomScans", "https://phantomscans.com", "en",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("PhoenixFansub", "https://phoenixfansub.com", "es",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("PiScans", "https://piscans.in", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "Rawkuma", "https://rawkuma.com/", "ja", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "Readkomik", "https://readkomik.com", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "SuryaScans", "https://suryascans.com", "en", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "SushiScan", "https://sushiscan.ru", "fr", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("TsundokuTraduções", "https://tsundoku.com.br", "pt-BR",
|
||||
// TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "TukangKomik", "https://tukangkomik.id", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source(
|
||||
// "WestManga", "https://westmanga.info", "id", TypeSource.mangathemesia)),
|
||||
// SourceModel(Source("xCaliBRScans", "https://xcalibrscans.com", "en",
|
||||
// TypeSource.mangathemesia)),
|
||||
// ];
|
||||
78
lib/source/source_model.dart
Normal file
78
lib/source/source_model.dart
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import 'package:hive/hive.dart';
|
||||
part 'source_model.g.dart';
|
||||
|
||||
@HiveType(typeId: 3)
|
||||
class SourceModel extends HiveObject {
|
||||
@HiveField(0)
|
||||
final String sourceName;
|
||||
@HiveField(1)
|
||||
final String url;
|
||||
@HiveField(2)
|
||||
final String lang;
|
||||
@HiveField(3, defaultValue: true)
|
||||
final bool isActive;
|
||||
@HiveField(4, defaultValue: false)
|
||||
final bool isAdded;
|
||||
@HiveField(5, defaultValue: false)
|
||||
final bool isNsfw;
|
||||
@HiveField(6)
|
||||
final TypeSource typeSource;
|
||||
SourceModel({
|
||||
required this.sourceName,
|
||||
required this.url,
|
||||
required this.lang,
|
||||
required this.typeSource,
|
||||
this.isActive = true,
|
||||
this.isAdded = false,
|
||||
this.isNsfw = false,
|
||||
});
|
||||
}
|
||||
|
||||
@HiveType(typeId: 4)
|
||||
enum TypeSource {
|
||||
@HiveField(1)
|
||||
single,
|
||||
@HiveField(2)
|
||||
mangathemesia,
|
||||
@HiveField(3)
|
||||
comick
|
||||
}
|
||||
|
||||
// @HiveType(typeId: 3)
|
||||
// class SourceModel {
|
||||
// @HiveField(0, defaultValue: true)
|
||||
// final bool isActive;
|
||||
// @HiveField(1)
|
||||
// final Source source;
|
||||
// @HiveField(2)
|
||||
// SourceModel(
|
||||
// this.source, {
|
||||
// this.isActive = true,
|
||||
// });
|
||||
// }
|
||||
|
||||
// @HiveType(typeId: 4)
|
||||
// class Source {
|
||||
// @HiveField(0)
|
||||
// final String sourceName;
|
||||
// @HiveField(1)
|
||||
// final String url;
|
||||
// @HiveField(2)
|
||||
// final String lang;
|
||||
// @HiveField(3, defaultValue: true)
|
||||
// final bool isActive;
|
||||
// @HiveField(4, defaultValue: false)
|
||||
// final bool isAdded;
|
||||
// @HiveField(5, defaultValue: false)
|
||||
// final bool isNsfw;
|
||||
// final TypeSource typeSource;
|
||||
// Source(
|
||||
// this.sourceName,
|
||||
// this.url,
|
||||
// this.lang,
|
||||
// this.typeSource, {
|
||||
// this.isActive = true,
|
||||
// this.isAdded = false,
|
||||
// this.isNsfw = false,
|
||||
// });
|
||||
// }
|
||||
103
lib/source/source_model.g.dart
Normal file
103
lib/source/source_model.g.dart
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'source_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class SourceModelAdapter extends TypeAdapter<SourceModel> {
|
||||
@override
|
||||
final int typeId = 3;
|
||||
|
||||
@override
|
||||
SourceModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return SourceModel(
|
||||
sourceName: fields[0] as String,
|
||||
url: fields[1] as String,
|
||||
lang: fields[2] as String,
|
||||
typeSource: fields[6] as TypeSource,
|
||||
isActive: fields[3] == null ? true : fields[3] as bool,
|
||||
isAdded: fields[4] == null ? false : fields[4] as bool,
|
||||
isNsfw: fields[5] == null ? false : fields[5] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, SourceModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.sourceName)
|
||||
..writeByte(1)
|
||||
..write(obj.url)
|
||||
..writeByte(2)
|
||||
..write(obj.lang)
|
||||
..writeByte(3)
|
||||
..write(obj.isActive)
|
||||
..writeByte(4)
|
||||
..write(obj.isAdded)
|
||||
..writeByte(5)
|
||||
..write(obj.isNsfw)
|
||||
..writeByte(6)
|
||||
..write(obj.typeSource);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is SourceModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
|
||||
class TypeSourceAdapter extends TypeAdapter<TypeSource> {
|
||||
@override
|
||||
final int typeId = 4;
|
||||
|
||||
@override
|
||||
TypeSource read(BinaryReader reader) {
|
||||
switch (reader.readByte()) {
|
||||
case 1:
|
||||
return TypeSource.single;
|
||||
case 2:
|
||||
return TypeSource.mangathemesia;
|
||||
case 3:
|
||||
return TypeSource.comick;
|
||||
default:
|
||||
return TypeSource.single;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, TypeSource obj) {
|
||||
switch (obj) {
|
||||
case TypeSource.single:
|
||||
writer.writeByte(1);
|
||||
break;
|
||||
case TypeSource.mangathemesia:
|
||||
writer.writeByte(2);
|
||||
break;
|
||||
case TypeSource.comick:
|
||||
writer.writeByte(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is TypeSourceAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
93
lib/utils/lang.dart
Normal file
93
lib/utils/lang.dart
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
lang(String lang) {
|
||||
if (lang == 'Français') {
|
||||
return 'fr';
|
||||
} else if (lang == 'English') {
|
||||
return 'en';
|
||||
} else if (lang == 'العربية') {
|
||||
return 'ar';
|
||||
} else if (lang == 'Português') {
|
||||
return 'pt';
|
||||
} else if (lang == 'Português do brasil') {
|
||||
return 'pt-br';
|
||||
} else if (lang == 'Italiano') {
|
||||
return 'it';
|
||||
} else if (lang == 'Pусский язык') {
|
||||
return 'ru';
|
||||
} else if (lang == 'Español') {
|
||||
return 'es';
|
||||
} else if (lang == 'Español latinoamericano') {
|
||||
return 'es-419';
|
||||
} else if (lang == 'Bahasa Indonesia') {
|
||||
return 'id';
|
||||
} else if (lang == 'हिन्दी, हिंदी') {
|
||||
return 'hi';
|
||||
} else if (lang == 'Deutsch') {
|
||||
return 'de';
|
||||
} else if (lang == '日本語') {
|
||||
return 'ja';
|
||||
} else if (lang == 'Türkçe') {
|
||||
return 'tr';
|
||||
} else if (lang == 'Polski') {
|
||||
return 'pl';
|
||||
} else if (lang == '中文') {
|
||||
return 'zh';
|
||||
} else if (lang == '(Hong Kong) 繁體中文') {
|
||||
return 'zh-hk';
|
||||
}
|
||||
}
|
||||
|
||||
completeLang(String lang) {
|
||||
if (lang == 'fr') {
|
||||
return 'Français';
|
||||
} else if (lang == 'en') {
|
||||
return 'English';
|
||||
} else if (lang == 'ar') {
|
||||
return 'العربية';
|
||||
} else if (lang == 'pt') {
|
||||
return 'Português';
|
||||
} else if (lang == 'pt-br') {
|
||||
return 'Português do brasil';
|
||||
} else if (lang == 'it') {
|
||||
return 'Italiano';
|
||||
} else if (lang == 'ru') {
|
||||
return 'Pусский язык';
|
||||
} else if (lang == 'es') {
|
||||
return 'Español';
|
||||
} else if (lang == 'es-419') {
|
||||
return 'Español latinoamericano';
|
||||
} else if (lang == 'id') {
|
||||
return 'Bahasa Indonesia';
|
||||
} else if (lang == 'hi') {
|
||||
return 'हिन्दी, हिंदी';
|
||||
} else if (lang == 'de') {
|
||||
return 'Deutsch';
|
||||
} else if (lang == 'ja') {
|
||||
return '日本語';
|
||||
} else if (lang == 'tr') {
|
||||
return 'Türkçe';
|
||||
} else if (lang == 'pl') {
|
||||
return 'Polski';
|
||||
} else if (lang == 'zh') {
|
||||
return '中文';
|
||||
} else if (lang == 'zh-hk') {
|
||||
return '(Hong Kong) 繁體中文';
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> language = [
|
||||
"Français",
|
||||
"English",
|
||||
"العربية",
|
||||
'Português',
|
||||
'Português do brasil',
|
||||
'Italiano',
|
||||
'Pусский язык',
|
||||
'Español',
|
||||
'Español latinoamericano',
|
||||
'Bahasa Indonesia',
|
||||
'हिन्दी, हिंदी',
|
||||
'日本語',
|
||||
'Deutsch',
|
||||
'中文',
|
||||
'(Hong Kong) 繁體中文'
|
||||
];
|
||||
|
|
@ -1,12 +1,30 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mangayomi/views/browse/extension.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mangayomi/views/browse/extension/extension.dart';
|
||||
import 'package:mangayomi/views/browse/migrate.dart';
|
||||
import 'package:mangayomi/views/browse/sources.dart';
|
||||
|
||||
class BrowseScreen extends StatelessWidget {
|
||||
class BrowseScreen extends StatefulWidget {
|
||||
const BrowseScreen({super.key});
|
||||
|
||||
@override
|
||||
State<BrowseScreen> createState() => _BrowseScreenState();
|
||||
}
|
||||
|
||||
class _BrowseScreenState extends State<BrowseScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_tabBarController = TabController(length: 3, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultTabController(
|
||||
|
|
@ -20,19 +38,33 @@ class BrowseScreen extends StatelessWidget {
|
|||
style: TextStyle(color: Theme.of(context).hintColor),
|
||||
),
|
||||
actions: [
|
||||
if (_tabBarController.index != 2)
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {},
|
||||
icon: Icon(
|
||||
_tabBarController.index == 0
|
||||
? Icons.travel_explore_rounded
|
||||
: Icons.search_rounded,
|
||||
color: Theme.of(context).hintColor)),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {},
|
||||
icon: Icon(Icons.travel_explore,
|
||||
color: Theme.of(context).hintColor)),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {},
|
||||
icon: Icon(Icons.filter_list_sharp,
|
||||
onPressed: () {
|
||||
if (_tabBarController.index == 0) {
|
||||
} else if (_tabBarController.index == 1) {
|
||||
context.push('/extensionLang');
|
||||
} else {}
|
||||
},
|
||||
icon: Icon(
|
||||
_tabBarController.index == 0
|
||||
? Icons.filter_list_sharp
|
||||
: _tabBarController.index == 1
|
||||
? Icons.translate_rounded
|
||||
: Icons.help_outline_outlined,
|
||||
color: Theme.of(context).hintColor)),
|
||||
],
|
||||
bottom: TabBar(
|
||||
labelColor: Theme.of(context).hintColor,
|
||||
controller: _tabBarController,
|
||||
isScrollable: true,
|
||||
tabs: const [
|
||||
Tab(text: "Sources"),
|
||||
|
|
@ -41,8 +73,11 @@ class BrowseScreen extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
body: const TabBarView(
|
||||
children: [SourcesScreen(), ExtensionScreen(), MigrateScreen()]),
|
||||
body: TabBarView(controller: _tabBarController, children: [
|
||||
SourcesScreen(),
|
||||
ExtensionScreen(),
|
||||
MigrateScreen()
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class ExtensionScreen extends StatefulWidget {
|
||||
const ExtensionScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ExtensionScreen> createState() => _ExtensionScreenState();
|
||||
}
|
||||
|
||||
class _ExtensionScreenState extends State<ExtensionScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {},
|
||||
leading: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey, borderRadius: BorderRadius.circular(5)),
|
||||
),
|
||||
subtitle: const Text('English'),
|
||||
title: const Text('MangaHere'),
|
||||
trailing: TextButton(onPressed: () {}, child: Text("Update")),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
82
lib/views/browse/extension/extension.dart
Normal file
82
lib/views/browse/extension/extension.dart
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/source/source_list.dart';
|
||||
import 'package:mangayomi/source/source_model.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/views/browse/extension/widgets/extension_list_tile_widget.dart';
|
||||
|
||||
class ExtensionScreen extends ConsumerStatefulWidget {
|
||||
const ExtensionScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<ExtensionScreen> createState() => _ExtensionScreenState();
|
||||
}
|
||||
|
||||
class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
||||
_init() {
|
||||
for (var element in sourcesList) {
|
||||
if (!ref
|
||||
.watch(hiveBoxMangaSourceProvider)
|
||||
.containsKey("${element.sourceName}${element.lang}")) {
|
||||
ref
|
||||
.watch(hiveBoxMangaSourceProvider)
|
||||
.put("${element.sourceName}${element.lang}", element);
|
||||
}
|
||||
}
|
||||
_isLoading = false;
|
||||
}
|
||||
|
||||
bool _isLoading = true;
|
||||
@override
|
||||
Widget build(
|
||||
BuildContext context,
|
||||
) {
|
||||
_init();
|
||||
return _isLoading
|
||||
? Container()
|
||||
: ValueListenableBuilder<Box<SourceModel>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaSourceProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries = value.values.toList();
|
||||
return GroupedListView<SourceModel, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => element.lang,
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8, left: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
completeLang(groupByValue.toLowerCase()),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, SourceModel element) {
|
||||
final source =
|
||||
value.get("${element.sourceName}${element.lang}")!;
|
||||
return ExtensionListTileWidget(
|
||||
lang:
|
||||
value.get("${element.sourceName}${element.lang}")!.lang,
|
||||
onChanged: (val) {
|
||||
value.put(
|
||||
"${element.sourceName}${element.lang}",
|
||||
SourceModel(
|
||||
sourceName: element.sourceName,
|
||||
url: element.url,
|
||||
lang: element.lang,
|
||||
typeSource: element.typeSource,
|
||||
isAdded: val));
|
||||
},
|
||||
sourceName: source.sourceName,
|
||||
value: source.isAdded,
|
||||
);
|
||||
},
|
||||
order: GroupedListOrder.ASC,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
44
lib/views/browse/extension/extension_lang.dart
Normal file
44
lib/views/browse/extension/extension_lang.dart
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/views/browse/extension/widgets/extension_lang_list_tile_widget.dart';
|
||||
|
||||
class ExtensionsLang extends ConsumerWidget {
|
||||
const ExtensionsLang({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Extensions"),
|
||||
),
|
||||
body: ValueListenableBuilder<Box<dynamic>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaFilterProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
List<dynamic> entries =
|
||||
value.get("language_filter", defaultValue: []);
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: language.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ExtensionLangListTileWidget(
|
||||
lang: lang(language[index]),
|
||||
onChanged: (val) {
|
||||
if (val == true) {
|
||||
entries.add("${lang(language[index])}_");
|
||||
value.put("language_filter", entries);
|
||||
} else {
|
||||
entries.remove("${lang(language[index])}_");
|
||||
value.put("language_filter", entries);
|
||||
}
|
||||
},
|
||||
value: entries.contains("${lang(language[index])}_"),
|
||||
);
|
||||
},
|
||||
);
|
||||
}));
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
|
||||
class ExtensionLangListTileWidget extends StatelessWidget {
|
||||
final String lang;
|
||||
final bool value;
|
||||
final Function(bool) onChanged;
|
||||
const ExtensionLangListTileWidget(
|
||||
{super.key,
|
||||
required this.lang,
|
||||
required this.value,
|
||||
required this.onChanged});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
onChanged(!value);
|
||||
},
|
||||
title: Text(completeLang(lang.toLowerCase())),
|
||||
trailing: Switch(
|
||||
value: value,
|
||||
onChanged: (value) {
|
||||
onChanged(value);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
|
||||
class ExtensionListTileWidget extends StatelessWidget {
|
||||
final String sourceName;
|
||||
final String lang;
|
||||
final bool value;
|
||||
final Function(bool) onChanged;
|
||||
const ExtensionListTileWidget(
|
||||
{super.key,
|
||||
required this.sourceName,
|
||||
required this.lang,
|
||||
required this.value,
|
||||
required this.onChanged});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
onChanged(!value);
|
||||
},
|
||||
leading: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor,
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: const Icon(Icons.source_outlined),
|
||||
),
|
||||
title: Text(sourceName),
|
||||
subtitle: Text(completeLang(lang.toLowerCase())),
|
||||
trailing: Switch(
|
||||
value: value,
|
||||
onChanged: (value) {
|
||||
onChanged(value);
|
||||
}));
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +1,131 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/models/manga_type.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/source/source_list.dart';
|
||||
import 'package:mangayomi/source/source_model.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
|
||||
class SourcesScreen extends StatefulWidget {
|
||||
// class SourcesScreen extends StatefulWidget {
|
||||
// const SourcesScreen({super.key});
|
||||
|
||||
// @override
|
||||
// State<SourcesScreen> createState() => _SourcesScreenState();
|
||||
// }
|
||||
|
||||
// class _SourcesScreenState extends State<SourcesScreen> {
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// ListTile(
|
||||
// onTap: () {
|
||||
// context.push('/mangaHome',
|
||||
// extra: MangaType(
|
||||
// isFullData: true, lang: 'en', source: 'MangaHere'));
|
||||
// },
|
||||
// leading: Container(
|
||||
// height: 37,
|
||||
// width: 37,
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.grey, borderRadius: BorderRadius.circular(5)),
|
||||
// ),
|
||||
// subtitle: const Text('English'),
|
||||
// title: const Text('MangaHere'),
|
||||
// trailing: SizedBox(
|
||||
// width: 110,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
// children: const [
|
||||
// Text(
|
||||
// "Latest",
|
||||
// style: TextStyle(fontWeight: FontWeight.bold),
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.push_pin_outlined,
|
||||
// color: Colors.black,
|
||||
// )
|
||||
// ],
|
||||
// )),
|
||||
// )
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
class SourcesScreen extends ConsumerStatefulWidget {
|
||||
const SourcesScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SourcesScreen> createState() => _SourcesScreenState();
|
||||
ConsumerState<SourcesScreen> createState() => _SourcesScreenState();
|
||||
}
|
||||
|
||||
class _SourcesScreenState extends State<SourcesScreen> {
|
||||
class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
context.push('/mangaHome',
|
||||
extra: MangaType(
|
||||
isFullData: true, lang: 'en', source: 'MangaHere'));
|
||||
},
|
||||
leading: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey, borderRadius: BorderRadius.circular(5)),
|
||||
),
|
||||
subtitle: const Text('English'),
|
||||
title: const Text('MangaHere'),
|
||||
trailing: SizedBox(
|
||||
width: 110,
|
||||
Widget build(
|
||||
BuildContext context,
|
||||
) {
|
||||
return ValueListenableBuilder<Box<SourceModel>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaSourceProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries =
|
||||
value.values.where((element) => element.isAdded == true).toList();
|
||||
if (entries.isEmpty) {
|
||||
return const Center(child: Text("Empty"));
|
||||
}
|
||||
return GroupedListView<SourceModel, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => element.lang,
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8, left: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: const [
|
||||
children: [
|
||||
Text(
|
||||
"Latest",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
completeLang(groupByValue.toLowerCase()),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Icon(
|
||||
Icons.push_pin_outlined,
|
||||
color: Colors.black,
|
||||
)
|
||||
],
|
||||
)),
|
||||
)
|
||||
],
|
||||
);
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, SourceModel element) {
|
||||
final source = value.get("${element.sourceName}${element.lang}")!;
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
if (source.sourceName == 'MangaHere') {
|
||||
context.push('/mangaHome',
|
||||
extra: MangaType(
|
||||
isFullData: true, lang: 'en', source: 'MangaHere'));
|
||||
}
|
||||
},
|
||||
leading: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor,
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: const Icon(Icons.source_outlined),
|
||||
),
|
||||
subtitle: Text(completeLang(source.lang)),
|
||||
title: Text(source.sourceName),
|
||||
trailing: SizedBox(
|
||||
width: 110,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.push_pin_outlined,
|
||||
color: Colors.black,
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
},
|
||||
sort: true,
|
||||
order: GroupedListOrder.ASC,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hidable/hidable.dart';
|
||||
import 'package:mangayomi/views/general/scroll_controller_provider.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
|
||||
class GeneralScreen extends ConsumerStatefulWidget {
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final scrollControllerProvider =
|
||||
Provider<ScrollController>((ref) => ScrollController());
|
||||
|
|
@ -5,7 +5,6 @@ import 'package:hive_flutter/hive_flutter.dart';
|
|||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/views/general/scroll_controller_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/gridview_widget.dart';
|
||||
|
|
@ -24,7 +23,6 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen> {
|
|||
final _textEditingController = TextEditingController();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = ref.watch(scrollControllerProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
|
|
@ -108,90 +106,52 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen> {
|
|||
}),
|
||||
],
|
||||
),
|
||||
body: _textEditingController.text.isNotEmpty
|
||||
? GridViewWidget(
|
||||
controller: scrollController,
|
||||
itemCount: entriesFilter.length,
|
||||
body: ValueListenableBuilder<Box<ModelManga>>(
|
||||
valueListenable: ref.watch(hiveBoxManga).listenable(),
|
||||
builder: (context, value, child) {
|
||||
entries = value.values.where((element) => element.favorite).toList();
|
||||
final entriesManga =
|
||||
_textEditingController.text.isNotEmpty ? entriesFilter : entries;
|
||||
if (entries.isNotEmpty || entriesFilter.isNotEmpty) {
|
||||
return GridViewWidget(
|
||||
itemCount: entriesManga.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final model = ModelManga(
|
||||
imageUrl: entriesFilter[index].imageUrl,
|
||||
name: entriesFilter[index].name,
|
||||
genre: entriesFilter[index].genre,
|
||||
author: entriesFilter[index].author,
|
||||
status: entriesFilter[index].status,
|
||||
chapterDate: entriesFilter[index].chapterDate,
|
||||
chapterTitle: entriesFilter[index].chapterTitle,
|
||||
chapterUrl: entriesFilter[index].chapterUrl,
|
||||
description: entriesFilter[index].description,
|
||||
favorite: entriesFilter[index].favorite,
|
||||
link: entriesFilter[index].link,
|
||||
source: entriesFilter[index].source,
|
||||
lang: entriesFilter[index].lang);
|
||||
imageUrl: entriesManga[index].imageUrl,
|
||||
name: entriesManga[index].name,
|
||||
genre: entriesManga[index].genre,
|
||||
author: entriesManga[index].author,
|
||||
status: entriesManga[index].status,
|
||||
chapterDate: entriesManga[index].chapterDate,
|
||||
chapterTitle: entriesManga[index].chapterTitle,
|
||||
chapterUrl: entriesManga[index].chapterUrl,
|
||||
description: entriesManga[index].description,
|
||||
favorite: entriesManga[index].favorite,
|
||||
link: entriesManga[index].link,
|
||||
source: entriesManga[index].source,
|
||||
lang: entriesManga[index].lang);
|
||||
|
||||
context.push('/manga-reader/detail', extra: model);
|
||||
},
|
||||
child: CoverViewWidget(
|
||||
children: [
|
||||
cachedNetworkImage(
|
||||
imageUrl: entriesFilter[index].imageUrl!,
|
||||
imageUrl: entriesManga[index].imageUrl!,
|
||||
width: 200,
|
||||
height: 270,
|
||||
fit: BoxFit.cover),
|
||||
BottomTextWidget(text: entriesFilter[index].name!)
|
||||
BottomTextWidget(text: entriesManga[index].name!)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: ValueListenableBuilder<Box<ModelManga>>(
|
||||
valueListenable: ref.watch(hiveBoxManga).listenable(),
|
||||
builder: (context, value, child) {
|
||||
entries =
|
||||
value.values.where((element) => element.favorite).toList();
|
||||
|
||||
if (entries.isNotEmpty) {
|
||||
return GridViewWidget(
|
||||
controller: scrollController,
|
||||
itemCount: entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final model = ModelManga(
|
||||
imageUrl: entries[index].imageUrl,
|
||||
name: entries[index].name,
|
||||
genre: entries[index].genre,
|
||||
author: entries[index].author,
|
||||
status: entries[index].status,
|
||||
chapterDate: entries[index].chapterDate,
|
||||
chapterTitle: entries[index].chapterTitle,
|
||||
chapterUrl: entries[index].chapterUrl,
|
||||
description: entries[index].description,
|
||||
favorite: entries[index].favorite,
|
||||
link: entries[index].link,
|
||||
source: entries[index].source,
|
||||
lang: entries[index].lang);
|
||||
|
||||
context.push('/manga-reader/detail', extra: model);
|
||||
},
|
||||
child: CoverViewWidget(
|
||||
children: [
|
||||
cachedNetworkImage(
|
||||
imageUrl: entries[index].imageUrl!,
|
||||
width: 200,
|
||||
height: 270,
|
||||
fit: BoxFit.cover),
|
||||
BottomTextWidget(text: entries[index].name!)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return const Center(child: Text("Empty Library"));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
return const Center(child: Text("Empty Library"));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView> {
|
|||
|
||||
_listView() {
|
||||
return DraggableScrollbar.rrect(
|
||||
alwaysVisibleScrollThumb: true,
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
|
|
@ -135,14 +136,17 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView> {
|
|||
modelManga: widget.modelManga!,
|
||||
index: finalIndex);
|
||||
},
|
||||
trailing: const Icon(FontAwesomeIcons.circleDown),
|
||||
trailing: const Icon(
|
||||
FontAwesomeIcons.circleDown,
|
||||
size: 20,
|
||||
),
|
||||
subtitle: Text(
|
||||
widget.modelManga!.chapterDate![finalIndex],
|
||||
style: const TextStyle(fontSize: 13),
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
title: Text(
|
||||
widget.modelManga!.chapterTitle![finalIndex],
|
||||
style: const TextStyle(fontSize: 15),
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
);
|
||||
}));
|
||||
|
|
@ -170,7 +174,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView> {
|
|||
Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: AppBar().preferredSize.height,
|
||||
height: AppBar().preferredSize.height * 1.5,
|
||||
),
|
||||
SizedBox(
|
||||
height: 180,
|
||||
|
|
@ -236,7 +240,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView> {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'${widget.modelManga!.chapterTitle!.length.toString()} chapter(s)',
|
||||
'${widget.modelManga!.chapterTitle!.length.toString()} chapters',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@ class MoreScreen extends StatelessWidget {
|
|||
flex: 3,
|
||||
child: Column(
|
||||
children: [
|
||||
const Divider(),
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading:
|
||||
const SizedBox(height: 40, child: Icon(Icons.cloud_off)),
|
||||
|
|
@ -28,7 +29,6 @@ class MoreScreen extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: const SizedBox(
|
||||
height: 40, child: Icon(CupertinoIcons.eyeglasses)),
|
||||
|
|
@ -39,16 +39,16 @@ class MoreScreen extends StatelessWidget {
|
|||
onChanged: (value) {},
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: const SizedBox(
|
||||
height: 40, child: Icon(Icons.download_outlined)),
|
||||
title: const Text('Donwload queue'),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: Container(
|
||||
height: 20,
|
||||
|
|
@ -58,7 +58,6 @@ class MoreScreen extends StatelessWidget {
|
|||
title: const Text('Categories'),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: Container(
|
||||
height: 20,
|
||||
|
|
@ -68,30 +67,28 @@ class MoreScreen extends StatelessWidget {
|
|||
title: const Text('Statistics'),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: const SizedBox(
|
||||
height: 40,
|
||||
child: Icon(Icons.settings_backup_restore_sharp)),
|
||||
title: const Text('Backup and restore'),
|
||||
),
|
||||
const Divider(),
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: const SizedBox(
|
||||
height: 40, child: Icon(Icons.settings_outlined)),
|
||||
title: const Text('Backup and restore'),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: const SizedBox(
|
||||
height: 40, child: Icon(Icons.info_outline)),
|
||||
title: const Text('About'),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {},
|
||||
leading: const SizedBox(
|
||||
height: 40, child: Icon(Icons.help_outline)),
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ class BottomTextWidget extends StatelessWidget {
|
|||
right: 0,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.3), //New
|
||||
offset: const Offset(0.5, 0.9),
|
||||
blurRadius: 3.0)
|
||||
],
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Colors.transparent, Colors.black.withOpacity(0.4)],
|
||||
stops: const [0, 1],
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
text,
|
||||
|
|
|
|||
|
|
@ -432,14 +432,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.2"
|
||||
hidable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hidable
|
||||
sha256: abe6f3ce1037a8de18e996d1e6417306949217010daea56799d6203a9d8f1c48
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
hive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
Loading…
Reference in a new issue