add novel support

This commit is contained in:
Schnitzel5 2024-11-24 19:49:57 +01:00
parent b2e25d26de
commit fb127f56b5
21 changed files with 349 additions and 97 deletions

View file

@ -1122,6 +1122,10 @@ Settings _settingsDeserialize(
libraryFilterMangasDownloadType: reader.readLongOrNull(offsets[53]),
libraryFilterMangasStartedType: reader.readLongOrNull(offsets[54]),
libraryFilterMangasUnreadType: reader.readLongOrNull(offsets[55]),
libraryFilterNovelBookMarkedType: reader.readLongOrNull(offsets[56]),
libraryFilterNovelDownloadType: reader.readLongOrNull(offsets[57]),
libraryFilterNovelStartedType: reader.readLongOrNull(offsets[58]),
libraryFilterNovelUnreadType: reader.readLongOrNull(offsets[59]),
libraryLocalSource: reader.readBoolOrNull(offsets[60]),
libraryShowCategoryTabs: reader.readBoolOrNull(offsets[61]),
libraryShowContinueReadingButton: reader.readBoolOrNull(offsets[62]),
@ -1132,6 +1136,15 @@ Settings _settingsDeserialize(
reader.readByteOrNull(offsets[67])] ??
DisplayType.comfortableGrid,
markEpisodeAsSeenType: reader.readLongOrNull(offsets[68]),
novelDisplayType: _SettingsnovelDisplayTypeValueEnumMap[
reader.readByteOrNull(offsets[69])] ??
DisplayType.comfortableGrid,
novelLibraryDownloadedChapters: reader.readBoolOrNull(offsets[71]),
novelLibraryLocalSource: reader.readBoolOrNull(offsets[72]),
novelLibraryShowCategoryTabs: reader.readBoolOrNull(offsets[73]),
novelLibraryShowContinueReadingButton: reader.readBoolOrNull(offsets[74]),
novelLibraryShowLanguage: reader.readBoolOrNull(offsets[75]),
novelLibraryShowNumbersOfItems: reader.readBoolOrNull(offsets[76]),
onlyIncludePinnedSources: reader.readBoolOrNull(offsets[77]),
pagePreloadAmount: reader.readLongOrNull(offsets[78]),
personalPageModeList: reader.readObjectList<PersonalPageMode>(
@ -1174,6 +1187,11 @@ Settings _settingsDeserialize(
SortLibraryMangaSchema.deserialize,
allOffsets,
),
sortLibraryNovel: reader.readObjectOrNull<SortLibraryManga>(
offsets[90],
SortLibraryMangaSchema.deserialize,
allOffsets,
),
startDatebackup: reader.readLongOrNull(offsets[91]),
syncAfterReading: reader.readBoolOrNull(offsets[92]),
syncOnAppLaunch: reader.readBoolOrNull(offsets[93]),
@ -1202,31 +1220,12 @@ Settings _settingsDeserialize(
allOffsets,
FilterScanlator(),
);
object.libraryFilterNovelBookMarkedType = reader.readLongOrNull(offsets[56]);
object.libraryFilterNovelDownloadType = reader.readLongOrNull(offsets[57]);
object.libraryFilterNovelStartedType = reader.readLongOrNull(offsets[58]);
object.libraryFilterNovelUnreadType = reader.readLongOrNull(offsets[59]);
object.locale = reader.readObjectOrNull<L10nLocale>(
offsets[65],
L10nLocaleSchema.deserialize,
allOffsets,
);
object.novelDisplayType = _SettingsnovelDisplayTypeValueEnumMap[
reader.readByteOrNull(offsets[69])] ??
DisplayType.compactGrid;
object.novelGridSize = reader.readLongOrNull(offsets[70]);
object.novelLibraryDownloadedChapters = reader.readBoolOrNull(offsets[71]);
object.novelLibraryLocalSource = reader.readBoolOrNull(offsets[72]);
object.novelLibraryShowCategoryTabs = reader.readBoolOrNull(offsets[73]);
object.novelLibraryShowContinueReadingButton =
reader.readBoolOrNull(offsets[74]);
object.novelLibraryShowLanguage = reader.readBoolOrNull(offsets[75]);
object.novelLibraryShowNumbersOfItems = reader.readBoolOrNull(offsets[76]);
object.sortLibraryNovel = reader.readObjectOrNull<SortLibraryManga>(
offsets[90],
SortLibraryMangaSchema.deserialize,
allOffsets,
);
return object;
}
@ -1439,7 +1438,7 @@ P _settingsDeserializeProp<P>(
case 69:
return (_SettingsnovelDisplayTypeValueEnumMap[
reader.readByteOrNull(offset)] ??
DisplayType.compactGrid) as P;
DisplayType.comfortableGrid) as P;
case 70:
return (reader.readLongOrNull(offset)) as P;
case 71:

View file

@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/providers/storage_provider.dart';
@ -75,8 +76,9 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
)
: Row(
children: [
if (_tabBarController.index == 2 ||
_tabBarController.index == 3)
if (_tabBarController.index == 3 ||
_tabBarController.index == 4 ||
_tabBarController.index == 5)
IconButton(
onPressed: () {
context.push('/createExtension');
@ -87,8 +89,9 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
? IconButton(
splashRadius: 20,
onPressed: () {
if (_tabBarController.index != 1 &&
_tabBarController.index != 0) {
if (_tabBarController.index != 0 &&
_tabBarController.index != 1 &&
_tabBarController.index != 2) {
setState(() {
_isSearch = true;
});
@ -101,7 +104,8 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
},
icon: Icon(
_tabBarController.index == 0 ||
_tabBarController.index == 1
_tabBarController.index == 1 ||
_tabBarController.index == 2
? Icons.travel_explore_rounded
: Icons.search_rounded,
color: Theme.of(context).hintColor))
@ -116,18 +120,24 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
} else if (_tabBarController.index == 1) {
context.push('/sourceFilter', extra: false);
} else if (_tabBarController.index == 2) {
_textEditingController.clear();
context.push('/ExtensionLang', extra: true);
context.push('/sourceFilter', extra: false);
} else if (_tabBarController.index == 3) {
_textEditingController.clear();
context.push('/ExtensionLang', extra: false);
} else if (_tabBarController.index == 4) {
_textEditingController.clear();
context.push('/ExtensionLang', extra: false);
} else if (_tabBarController.index == 5) {
_textEditingController.clear();
context.push('/ExtensionLang', extra: false);
} else {}
},
icon: Icon(
_tabBarController.index == 0 || _tabBarController.index == 1
_tabBarController.index == 0 || _tabBarController.index == 1 || _tabBarController.index == 2
? Icons.filter_list_sharp
: _tabBarController.index == 2 ||
_tabBarController.index == 3
: _tabBarController.index == 3 ||
_tabBarController.index == 4 ||
_tabBarController.index == 5
? Icons.translate_rounded
: Icons.help_outline_outlined,
color: Theme.of(context).hintColor)),
@ -139,12 +149,13 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
tabs: [
Tab(text: l10n.manga_sources),
Tab(text: l10n.anime_sources),
Tab(text: l10n.novel_sources),
Tab(
child: Row(
children: [
Text(l10n.manga_extensions),
const SizedBox(width: 8),
_extensionUpdateNumbers(ref, true)
_extensionUpdateNumbers(ref, ItemType.manga)
],
),
),
@ -153,7 +164,16 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
children: [
Text(l10n.anime_extensions),
const SizedBox(width: 8),
_extensionUpdateNumbers(ref, false)
_extensionUpdateNumbers(ref, ItemType.anime)
],
),
),
Tab(
child: Row(
children: [
Text(l10n.novel_extensions),
const SizedBox(width: 8),
_extensionUpdateNumbers(ref, ItemType.novel)
],
),
),
@ -163,24 +183,34 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
),
body: TabBarView(controller: _tabBarController, children: [
SourcesScreen(
isManga: true,
itemType: ItemType.manga,
tabIndex: (index) {
_tabBarController.animateTo(index);
},
),
SourcesScreen(
isManga: false,
itemType: ItemType.anime,
tabIndex: (index) {
_tabBarController.animateTo(index);
},
),
SourcesScreen(
itemType: ItemType.novel,
tabIndex: (index) {
_tabBarController.animateTo(index);
},
),
ExtensionScreen(
query: _textEditingController.text,
isManga: true,
itemType: ItemType.manga,
),
ExtensionScreen(
query: _textEditingController.text,
isManga: false,
itemType: ItemType.anime,
),
ExtensionScreen(
query: _textEditingController.text,
itemType: ItemType.novel,
),
// const MigrateScreen()
]),
@ -189,14 +219,14 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
}
}
Widget _extensionUpdateNumbers(WidgetRef ref, bool isManga) {
Widget _extensionUpdateNumbers(WidgetRef ref, ItemType itemType) {
return StreamBuilder(
stream: isar.sources
.filter()
.idIsNotNull()
.and()
.isActiveEqualTo(true)
.isMangaEqualTo(isManga)
.itemTypeEqualTo(itemType)
.watch(fireImmediately: true),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {

View file

@ -1,21 +1,23 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/modules/browse/extension/providers/extensions_provider.dart';
import 'package:mangayomi/services/fetch_anime_sources.dart';
import 'package:mangayomi/services/fetch_manga_sources.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/fetch_novel_sources.dart';
import 'package:mangayomi/services/fetch_sources_list.dart';
import 'package:mangayomi/utils/language.dart';
import 'package:mangayomi/modules/browse/extension/widgets/extension_list_tile_widget.dart';
class ExtensionScreen extends ConsumerStatefulWidget {
final bool isManga;
final ItemType itemType;
final String query;
const ExtensionScreen(
{required this.query, required this.isManga, super.key});
{required this.query, required this.itemType, super.key});
@override
ConsumerState<ExtensionScreen> createState() => _ExtensionScreenState();
@ -26,19 +28,24 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
@override
Widget build(BuildContext context) {
final streamExtensions =
ref.watch(getExtensionsStreamProvider(widget.isManga));
if (widget.isManga) {
ref.watch(getExtensionsStreamProvider(widget.itemType));
if (widget.itemType == ItemType.manga) {
ref.watch(fetchMangaSourcesListProvider(id: null, reFresh: false));
} else {
} else if (widget.itemType == ItemType.anime) {
ref.watch(fetchAnimeSourcesListProvider(id: null, reFresh: false));
} else {
ref.watch(fetchNovelSourcesListProvider(id: null, reFresh: false));
}
final l10n = l10nLocalizations(context)!;
return RefreshIndicator(
onRefresh: () => widget.isManga
onRefresh: () => widget.itemType == ItemType.manga
? ref.refresh(
fetchMangaSourcesListProvider(id: null, reFresh: true).future)
: ref.refresh(
fetchAnimeSourcesListProvider(id: null, reFresh: true).future),
: widget.itemType == ItemType.anime
? ref.refresh(
fetchAnimeSourcesListProvider(id: null, reFresh: true).future) :
ref.refresh(
fetchNovelSourcesListProvider(id: null, reFresh: true).future),
child: Padding(
padding: const EdgeInsets.only(top: 10),
child: streamExtensions.when(
@ -87,14 +94,19 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
ElevatedButton(
onPressed: () async {
for (var source in updateEntries) {
source.isManga!
source.itemType == ItemType.manga
? await ref.watch(
fetchMangaSourcesListProvider(
id: source.id, reFresh: true)
.future)
: await ref.watch(
: source.itemType == ItemType.anime ?
await ref.watch(
fetchAnimeSourcesListProvider(
id: source.id, reFresh: true)
.future) :
await ref.watch(
fetchNovelSourcesListProvider(
id: source.id, reFresh: true)
.future);
}
},
@ -167,12 +179,15 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
error: (error, _) => Center(
child: ElevatedButton(
onPressed: () {
if (widget.isManga) {
if (widget.itemType == ItemType.manga) {
ref.invalidate(
fetchMangaSourcesListProvider(id: null, reFresh: true));
} else {
} else if (widget.itemType == ItemType.anime) {
ref.invalidate(
fetchAnimeSourcesListProvider(id: null, reFresh: true));
} else {
ref.invalidate(
fetchNovelSourcesListProvider(id: null, reFresh: true));
}
},
child: Text(context.l10n.refresh)),

View file

@ -1,17 +1,18 @@
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/source.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
part 'extensions_provider.g.dart';
@riverpod
Stream<List<Source>> getExtensionsStream(Ref ref, bool? isManga) async* {
Stream<List<Source>> getExtensionsStream(Ref ref, ItemType itemType) async* {
yield* isar.sources
.filter()
.idIsNotNull()
.and()
.isActiveEqualTo(true)
.isMangaEqualTo(isManga)
.itemTypeEqualTo(itemType)
.watch(fireImmediately: true);
}

View file

@ -7,7 +7,7 @@ part of 'extensions_provider.dart';
// **************************************************************************
String _$getExtensionsStreamHash() =>
r'62f2884dd64a2f3d8928f7399c6b2547f0311078';
r'3c5d6625c40c222f25fc8141df078dd46bcc762f';
/// Copied from Dart SDK
class _SystemHash {
@ -41,10 +41,10 @@ class GetExtensionsStreamFamily extends Family<AsyncValue<List<Source>>> {
/// See also [getExtensionsStream].
GetExtensionsStreamProvider call(
bool? isManga,
ItemType itemType,
) {
return GetExtensionsStreamProvider(
isManga,
itemType,
);
}
@ -53,7 +53,7 @@ class GetExtensionsStreamFamily extends Family<AsyncValue<List<Source>>> {
covariant GetExtensionsStreamProvider provider,
) {
return call(
provider.isManga,
provider.itemType,
);
}
@ -77,11 +77,11 @@ class GetExtensionsStreamProvider
extends AutoDisposeStreamProvider<List<Source>> {
/// See also [getExtensionsStream].
GetExtensionsStreamProvider(
bool? isManga,
ItemType itemType,
) : this._internal(
(ref) => getExtensionsStream(
ref as GetExtensionsStreamRef,
isManga,
itemType,
),
from: getExtensionsStreamProvider,
name: r'getExtensionsStreamProvider',
@ -92,7 +92,7 @@ class GetExtensionsStreamProvider
dependencies: GetExtensionsStreamFamily._dependencies,
allTransitiveDependencies:
GetExtensionsStreamFamily._allTransitiveDependencies,
isManga: isManga,
itemType: itemType,
);
GetExtensionsStreamProvider._internal(
@ -102,10 +102,10 @@ class GetExtensionsStreamProvider
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.isManga,
required this.itemType,
}) : super.internal();
final bool? isManga;
final ItemType itemType;
@override
Override overrideWith(
@ -120,7 +120,7 @@ class GetExtensionsStreamProvider
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
isManga: isManga,
itemType: itemType,
),
);
}
@ -132,13 +132,13 @@ class GetExtensionsStreamProvider
@override
bool operator ==(Object other) {
return other is GetExtensionsStreamProvider && other.isManga == isManga;
return other is GetExtensionsStreamProvider && other.itemType == itemType;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, isManga.hashCode);
hash = _SystemHash.combine(hash, itemType.hashCode);
return _SystemHash.finish(hash);
}
@ -147,8 +147,8 @@ class GetExtensionsStreamProvider
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin GetExtensionsStreamRef on AutoDisposeStreamProviderRef<List<Source>> {
/// The parameter `isManga` of this provider.
bool? get isManga;
/// The parameter `itemType` of this provider.
ItemType get itemType;
}
class _GetExtensionsStreamProviderElement
@ -157,7 +157,7 @@ class _GetExtensionsStreamProviderElement
_GetExtensionsStreamProviderElement(super.provider);
@override
bool? get isManga => (origin as GetExtensionsStreamProvider).isManga;
ItemType get itemType => (origin as GetExtensionsStreamProvider).itemType;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View file

@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/modules/browse/sources/widgets/source_list_tile.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
@ -10,9 +11,9 @@ import 'package:mangayomi/utils/language.dart';
class SourcesScreen extends ConsumerStatefulWidget {
final Function(int) tabIndex;
final bool isManga;
final ItemType itemType;
const SourcesScreen(
{required this.tabIndex, required this.isManga, super.key});
{required this.tabIndex, required this.itemType, super.key});
@override
ConsumerState<SourcesScreen> createState() => _SourcesScreenState();
@ -33,7 +34,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
.and()
.isActiveEqualTo(true)
.and()
.isMangaEqualTo(widget.isManga)
.itemTypeEqualTo(widget.itemType)
.watch(fireImmediately: true),
builder: (context, snapshot) {
if (!snapshot.hasData) {
@ -52,7 +53,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
padding: const EdgeInsets.all(8.0),
child: ElevatedButton.icon(
onPressed: () =>
widget.tabIndex(widget.isManga ? 2 : 3),
widget.tabIndex(widget.itemType == ItemType.manga ? 3 : widget.itemType == ItemType.anime ? 4 : 5),
icon: const Icon(Icons.extension_rounded),
label: Text(context.l10n.show_extensions)),
)
@ -91,7 +92,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
itemBuilder: (context, Source element) {
return SourceListTile(
source: element,
isManga: widget.isManga,
itemType: widget.itemType,
);
},
groupComparator: (group1, group2) =>
@ -118,7 +119,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
itemBuilder: (context, Source element) {
return SourceListTile(
source: element,
isManga: widget.isManga,
itemType: widget.itemType,
);
},
groupComparator: (group1, group2) =>
@ -146,7 +147,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
itemBuilder: (context, Source element) {
return SourceListTile(
source: element,
isManga: widget.isManga,
itemType: widget.itemType,
);
},
groupComparator: (group1, group2) =>

View file

@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/cached_network.dart';
@ -10,10 +11,10 @@ import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:mangayomi/utils/language.dart';
class SourceListTile extends StatelessWidget {
final bool isManga;
final ItemType itemType;
final Source source;
const SourceListTile(
{super.key, required this.source, required this.isManga});
{super.key, required this.source, required this.itemType});
@override
Widget build(BuildContext context) {
@ -23,7 +24,7 @@ class SourceListTile extends StatelessWidget {
.filter()
.idIsNotNull()
.and()
.isMangaEqualTo(isManga)
.itemTypeEqualTo(itemType)
.findAllSync();
isar.writeTxnSync(() {
for (var src in sources) {

View file

@ -34,7 +34,7 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen>
@override
void initState() {
_tabBarController = TabController(length: 2, vsync: this);
_tabBarController = TabController(length: 3, vsync: this);
_tabBarController.animateTo(0);
_tabBarController.addListener(() {
setState(() {

View file

@ -7,7 +7,7 @@ part of 'isar_providers.dart';
// **************************************************************************
String _$getAllHistoryStreamHash() =>
r'53b3a7837efab9e7d2808930e5070dbd788c59f8';
r'42048cb03035be55b52fc501fb2309cdb2acfcb8';
/// Copied from Dart SDK
class _SystemHash {
@ -161,7 +161,7 @@ class _GetAllHistoryStreamProviderElement
}
String _$getAllUpdateStreamHash() =>
r'01f77807c8be11f471b6acee6e7bc358ce600a65';
r'6a20f8feba3010c2ab7a80560f7a7f6cf10c7366';
/// See also [getAllUpdateStream].
@ProviderFor(getAllUpdateStream)

View file

@ -7,7 +7,7 @@ part of 'add_torrent.dart';
// **************************************************************************
String _$addTorrentFromUrlOrFromFileHash() =>
r'8102259b30765a5c5cc57870f5c583bd5d421eee';
r'11cc239bb8b517326f9a005b0c89dd5eb1127099';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'isar_providers.dart';
// RiverpodGenerator
// **************************************************************************
String _$getAllMangaStreamHash() => r'1c0b5442ae86b2fa899d509a555f5d375f0ff79a';
String _$getAllMangaStreamHash() => r'5e86a22a68ca1a52aefa9c0bc675d284369beac5';
/// Copied from Dart SDK
class _SystemHash {
@ -176,7 +176,7 @@ class _GetAllMangaStreamProviderElement
}
String _$getAllMangaWithoutCategoriesStreamHash() =>
r'78076f291274b7defd9567e55314002d9aeecab1';
r'61ea54070c7e87a45aeabce5fd21366faaf4ae6d';
/// See also [getAllMangaWithoutCategoriesStream].
@ProviderFor(getAllMangaWithoutCategoriesStream)

View file

@ -7,7 +7,7 @@ part of 'local_archive.dart';
// **************************************************************************
String _$importArchivesFromFileHash() =>
r'8be95f0947ab5247e3305a355a6f17f0aaecad00';
r'8e6e592c927ad080e93d54dac1144ef8637a7e52';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -43,10 +43,10 @@ class MainScreen extends ConsumerWidget {
int currentIndex = switch (location) {
null || '/MangaLibrary' => 0,
'/AnimeLibrary' => 1,
'/updates' => 2,
'/history' => 3,
'/browse' => 4,
'/NovelLibrary' => 5,
'/NovelLibrary' => 2,
'/updates' => 3,
'/history' => 4,
'/browse' => 5,
_ => 6,
};
@ -259,6 +259,12 @@ class MainScreen extends ConsumerWidget {
icon: const Icon(
Icons.video_collection_outlined),
label: l10n.anime),
NavigationDestination(
selectedIcon:
const Icon(Icons.local_library),
icon: const Icon(
Icons.local_library_outlined),
label: l10n.novel),
Stack(
children: [
NavigationDestination(
@ -298,9 +304,10 @@ class MainScreen extends ConsumerWidget {
final fn = switch (newIndex) {
0 => route.go('/MangaLibrary'),
1 => route.go('/AnimeLibrary'),
2 => route.go('/updates'),
3 => route.go('/history'),
4 => route.go('/browse'),
2 => route.go('/NovelLibrary'),
3 => route.go('/updates'),
4 => route.go('/history'),
5 => route.go('/browse'),
_ => route.go('/more'),
};
fn;

View file

@ -6,7 +6,7 @@ part of 'migration.dart';
// RiverpodGenerator
// **************************************************************************
String _$migrationHash() => r'a302c6da3c1545c952a28e76a6d0b7af3fde1e7a';
String _$migrationHash() => r'403da626b6a797854dde7ae77b4ea452300c40e6';
/// See also [migration].
@ProviderFor(migration)

View file

@ -6,7 +6,7 @@ part of 'update_manga_detail_providers.dart';
// RiverpodGenerator
// **************************************************************************
String _$updateMangaDetailHash() => r'29a10d49454febb4fe88ca9c007d3512d812bf84';
String _$updateMangaDetailHash() => r'a058dcca7f99974e89fce2aa7f048edf1a0f7854';
/// Copied from Dart SDK
class _SystemHash {

View file

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

View file

@ -22,7 +22,7 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
late TabController _tabBarController;
@override
void initState() {
_tabBarController = TabController(length: 2, vsync: this);
_tabBarController = TabController(length: 3, vsync: this);
_tabBarController.animateTo(widget.data.$2);
super.initState();

View file

@ -7,7 +7,7 @@ part of 'isar_providers.dart';
// **************************************************************************
String _$getMangaCategorieStreamHash() =>
r'97e90977f4696eedcf597c655a40dd6ccd47ed37';
r'1dcf15018a6467eef7a26c1728b9e531ebd984d0';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -72,7 +72,7 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
@override
void initState() {
_tabBarController = TabController(length: 2, vsync: this);
_tabBarController = TabController(length: 3, vsync: this);
_tabBarController.animateTo(0);
_tabBarController.addListener(() {
setState(() {

View file

@ -0,0 +1,19 @@
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
import 'package:mangayomi/services/fetch_sources_list.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
part 'fetch_novel_sources.g.dart';
@riverpod
Future fetchNovelSourcesList(Ref ref,
{int? id, required reFresh}) async {
if (ref.watch(checkForExtensionsUpdateStateProvider) || reFresh) {
await fetchSourcesList(
sourcesIndexUrl:
"https://kodjodevf.github.io/mangayomi-extensions/index.json",
refresh: reFresh,
id: id,
ref: ref,
isManga: true);
}
}

View file

@ -0,0 +1,179 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'fetch_novel_sources.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$fetchNovelSourcesListHash() =>
r'110b23568136e32ebfba7e5414bdf524881a8579';
/// Copied from Dart SDK
class _SystemHash {
_SystemHash._();
static int combine(int hash, int value) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + value);
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
// ignore: parameter_assignments
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
}
/// See also [fetchNovelSourcesList].
@ProviderFor(fetchNovelSourcesList)
const fetchNovelSourcesListProvider = FetchNovelSourcesListFamily();
/// See also [fetchNovelSourcesList].
class FetchNovelSourcesListFamily extends Family<AsyncValue> {
/// See also [fetchNovelSourcesList].
const FetchNovelSourcesListFamily();
/// See also [fetchNovelSourcesList].
FetchNovelSourcesListProvider call({
int? id,
required dynamic reFresh,
}) {
return FetchNovelSourcesListProvider(
id: id,
reFresh: reFresh,
);
}
@override
FetchNovelSourcesListProvider getProviderOverride(
covariant FetchNovelSourcesListProvider provider,
) {
return call(
id: provider.id,
reFresh: provider.reFresh,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'fetchNovelSourcesListProvider';
}
/// See also [fetchNovelSourcesList].
class FetchNovelSourcesListProvider extends AutoDisposeFutureProvider<Object?> {
/// See also [fetchNovelSourcesList].
FetchNovelSourcesListProvider({
int? id,
required dynamic reFresh,
}) : this._internal(
(ref) => fetchNovelSourcesList(
ref as FetchNovelSourcesListRef,
id: id,
reFresh: reFresh,
),
from: fetchNovelSourcesListProvider,
name: r'fetchNovelSourcesListProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$fetchNovelSourcesListHash,
dependencies: FetchNovelSourcesListFamily._dependencies,
allTransitiveDependencies:
FetchNovelSourcesListFamily._allTransitiveDependencies,
id: id,
reFresh: reFresh,
);
FetchNovelSourcesListProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.id,
required this.reFresh,
}) : super.internal();
final int? id;
final dynamic reFresh;
@override
Override overrideWith(
FutureOr<Object?> Function(FetchNovelSourcesListRef provider) create,
) {
return ProviderOverride(
origin: this,
override: FetchNovelSourcesListProvider._internal(
(ref) => create(ref as FetchNovelSourcesListRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
id: id,
reFresh: reFresh,
),
);
}
@override
AutoDisposeFutureProviderElement<Object?> createElement() {
return _FetchNovelSourcesListProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is FetchNovelSourcesListProvider &&
other.id == id &&
other.reFresh == reFresh;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, id.hashCode);
hash = _SystemHash.combine(hash, reFresh.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin FetchNovelSourcesListRef on AutoDisposeFutureProviderRef<Object?> {
/// The parameter `id` of this provider.
int? get id;
/// The parameter `reFresh` of this provider.
dynamic get reFresh;
}
class _FetchNovelSourcesListProviderElement
extends AutoDisposeFutureProviderElement<Object?>
with FetchNovelSourcesListRef {
_FetchNovelSourcesListProviderElement(super.provider);
@override
int? get id => (origin as FetchNovelSourcesListProvider).id;
@override
dynamic get reFresh => (origin as FetchNovelSourcesListProvider).reFresh;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package