From 43be09db8fa070a045affd129214330e005b8590 Mon Sep 17 00:00:00 2001 From: kodjomoustapha <107993382+kodjodevf@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:36:00 +0100 Subject: [PATCH] feat/pick-cover-image-from-trackers -ability to choose anime/manga cover image from trackers as custom image --- lib/models/manga.dart | 9 +- lib/models/manga.g.dart | 322 +++++++++++++++--- .../anime_player_controller_provider.g.dart | 2 +- .../global_search/global_search_screen.dart | 56 ++- lib/modules/history/history_screen.dart | 5 +- .../providers/library_state_provider.g.dart | 4 +- .../widgets/library_gridview_widget.dart | 2 +- .../widgets/library_listview_widget.dart | 4 +- .../manga/detail/manga_detail_view.dart | 159 +++++---- .../update_manga_detail_providers.g.dart | 2 +- .../detail/widgets/tracker_search_widget.dart | 25 +- .../reader_controller_provider.g.dart | 2 +- .../widgets/manga_image_card_widget.dart | 44 +-- lib/services/trackers/kitsu.g.dart | 2 +- lib/utils/headers.g.dart | 2 +- 15 files changed, 439 insertions(+), 201 deletions(-) diff --git a/lib/models/manga.dart b/lib/models/manga.dart index f0d41848..7199ec79 100644 --- a/lib/models/manga.dart +++ b/lib/models/manga.dart @@ -42,6 +42,8 @@ class Manga { List? customCoverImage; + String? customCoverFromTracker; + @Backlink(to: "manga") final chapters = IsarLinks(); @@ -63,7 +65,8 @@ class Manga { this.categories, this.lastRead = 0, this.isLocalArchive = false, - this.customCoverImage}); + this.customCoverImage, + this.customCoverFromTracker}); Manga.fromJson(Map json) { author = json['author']; @@ -84,6 +87,7 @@ class Manga { name = json['name']; source = json['source']; status = Status.values[json['status']]; + customCoverFromTracker = json['customCoverFromTracker']; } Map toJson() => { @@ -104,7 +108,8 @@ class Manga { 'link': link, 'name': name, 'source': source, - 'status': status.index + 'status': status.index, + 'customCoverFromTracker': customCoverFromTracker, }; } diff --git a/lib/models/manga.g.dart b/lib/models/manga.g.dart index 23851cae..bdade26b 100644 --- a/lib/models/manga.g.dart +++ b/lib/models/manga.g.dart @@ -27,78 +27,83 @@ const MangaSchema = CollectionSchema( name: r'categories', type: IsarType.longList, ), - r'customCoverImage': PropertySchema( + r'customCoverFromTracker': PropertySchema( id: 2, + name: r'customCoverFromTracker', + type: IsarType.string, + ), + r'customCoverImage': PropertySchema( + id: 3, name: r'customCoverImage', type: IsarType.byteList, ), r'dateAdded': PropertySchema( - id: 3, + id: 4, name: r'dateAdded', type: IsarType.long, ), r'description': PropertySchema( - id: 4, + id: 5, name: r'description', type: IsarType.string, ), r'favorite': PropertySchema( - id: 5, + id: 6, name: r'favorite', type: IsarType.bool, ), r'genre': PropertySchema( - id: 6, + id: 7, name: r'genre', type: IsarType.stringList, ), r'imageUrl': PropertySchema( - id: 7, + id: 8, name: r'imageUrl', type: IsarType.string, ), r'isLocalArchive': PropertySchema( - id: 8, + id: 9, name: r'isLocalArchive', type: IsarType.bool, ), r'isManga': PropertySchema( - id: 9, + id: 10, name: r'isManga', type: IsarType.bool, ), r'lang': PropertySchema( - id: 10, + id: 11, name: r'lang', type: IsarType.string, ), r'lastRead': PropertySchema( - id: 11, + id: 12, name: r'lastRead', type: IsarType.long, ), r'lastUpdate': PropertySchema( - id: 12, + id: 13, name: r'lastUpdate', type: IsarType.long, ), r'link': PropertySchema( - id: 13, + id: 14, name: r'link', type: IsarType.string, ), r'name': PropertySchema( - id: 14, + id: 15, name: r'name', type: IsarType.string, ), r'source': PropertySchema( - id: 15, + id: 16, name: r'source', type: IsarType.string, ), r'status': PropertySchema( - id: 16, + id: 17, name: r'status', type: IsarType.byte, enumMap: _MangastatusEnumValueMap, @@ -144,6 +149,12 @@ int _mangaEstimateSize( bytesCount += 3 + value.length * 8; } } + { + final value = object.customCoverFromTracker; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } { final value = object.customCoverImage; if (value != null) { @@ -209,21 +220,22 @@ void _mangaSerialize( ) { writer.writeString(offsets[0], object.author); writer.writeLongList(offsets[1], object.categories); - writer.writeByteList(offsets[2], object.customCoverImage); - writer.writeLong(offsets[3], object.dateAdded); - writer.writeString(offsets[4], object.description); - writer.writeBool(offsets[5], object.favorite); - writer.writeStringList(offsets[6], object.genre); - writer.writeString(offsets[7], object.imageUrl); - writer.writeBool(offsets[8], object.isLocalArchive); - writer.writeBool(offsets[9], object.isManga); - writer.writeString(offsets[10], object.lang); - writer.writeLong(offsets[11], object.lastRead); - writer.writeLong(offsets[12], object.lastUpdate); - writer.writeString(offsets[13], object.link); - writer.writeString(offsets[14], object.name); - writer.writeString(offsets[15], object.source); - writer.writeByte(offsets[16], object.status.index); + writer.writeString(offsets[2], object.customCoverFromTracker); + writer.writeByteList(offsets[3], object.customCoverImage); + writer.writeLong(offsets[4], object.dateAdded); + writer.writeString(offsets[5], object.description); + writer.writeBool(offsets[6], object.favorite); + writer.writeStringList(offsets[7], object.genre); + writer.writeString(offsets[8], object.imageUrl); + writer.writeBool(offsets[9], object.isLocalArchive); + writer.writeBool(offsets[10], object.isManga); + writer.writeString(offsets[11], object.lang); + writer.writeLong(offsets[12], object.lastRead); + writer.writeLong(offsets[13], object.lastUpdate); + writer.writeString(offsets[14], object.link); + writer.writeString(offsets[15], object.name); + writer.writeString(offsets[16], object.source); + writer.writeByte(offsets[17], object.status.index); } Manga _mangaDeserialize( @@ -235,22 +247,23 @@ Manga _mangaDeserialize( final object = Manga( author: reader.readStringOrNull(offsets[0]), categories: reader.readLongList(offsets[1]), - customCoverImage: reader.readByteList(offsets[2]), - dateAdded: reader.readLongOrNull(offsets[3]), - description: reader.readStringOrNull(offsets[4]), - favorite: reader.readBoolOrNull(offsets[5]), - genre: reader.readStringList(offsets[6]), + customCoverFromTracker: reader.readStringOrNull(offsets[2]), + customCoverImage: reader.readByteList(offsets[3]), + dateAdded: reader.readLongOrNull(offsets[4]), + description: reader.readStringOrNull(offsets[5]), + favorite: reader.readBoolOrNull(offsets[6]), + genre: reader.readStringList(offsets[7]), id: id, - imageUrl: reader.readStringOrNull(offsets[7]), - isLocalArchive: reader.readBoolOrNull(offsets[8]), - isManga: reader.readBoolOrNull(offsets[9]), - lang: reader.readStringOrNull(offsets[10]), - lastRead: reader.readLongOrNull(offsets[11]), - lastUpdate: reader.readLongOrNull(offsets[12]), - link: reader.readStringOrNull(offsets[13]), - name: reader.readStringOrNull(offsets[14]), - source: reader.readStringOrNull(offsets[15]), - status: _MangastatusValueEnumMap[reader.readByteOrNull(offsets[16])] ?? + imageUrl: reader.readStringOrNull(offsets[8]), + isLocalArchive: reader.readBoolOrNull(offsets[9]), + isManga: reader.readBoolOrNull(offsets[10]), + lang: reader.readStringOrNull(offsets[11]), + lastRead: reader.readLongOrNull(offsets[12]), + lastUpdate: reader.readLongOrNull(offsets[13]), + link: reader.readStringOrNull(offsets[14]), + name: reader.readStringOrNull(offsets[15]), + source: reader.readStringOrNull(offsets[16]), + status: _MangastatusValueEnumMap[reader.readByteOrNull(offsets[17])] ?? Status.ongoing, ); return object; @@ -268,34 +281,36 @@ P _mangaDeserializeProp

( case 1: return (reader.readLongList(offset)) as P; case 2: - return (reader.readByteList(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 3: - return (reader.readLongOrNull(offset)) as P; + return (reader.readByteList(offset)) as P; case 4: - return (reader.readStringOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 5: - return (reader.readBoolOrNull(offset)) as P; - case 6: - return (reader.readStringList(offset)) as P; - case 7: return (reader.readStringOrNull(offset)) as P; - case 8: + case 6: return (reader.readBoolOrNull(offset)) as P; + case 7: + return (reader.readStringList(offset)) as P; + case 8: + return (reader.readStringOrNull(offset)) as P; case 9: return (reader.readBoolOrNull(offset)) as P; case 10: - return (reader.readStringOrNull(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 11: - return (reader.readLongOrNull(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 12: return (reader.readLongOrNull(offset)) as P; case 13: - return (reader.readStringOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 14: return (reader.readStringOrNull(offset)) as P; case 15: return (reader.readStringOrNull(offset)) as P; case 16: + return (reader.readStringOrNull(offset)) as P; + case 17: return (_MangastatusValueEnumMap[reader.readByteOrNull(offset)] ?? Status.ongoing) as P; default: @@ -708,6 +723,162 @@ extension MangaQueryFilter on QueryBuilder { }); } + QueryBuilder + customCoverFromTrackerIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'customCoverFromTracker', + )); + }); + } + + QueryBuilder + customCoverFromTrackerIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'customCoverFromTracker', + )); + }); + } + + QueryBuilder + customCoverFromTrackerEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'customCoverFromTracker', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'customCoverFromTracker', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'customCoverFromTracker', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'customCoverFromTracker', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'customCoverFromTracker', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'customCoverFromTracker', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'customCoverFromTracker', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'customCoverFromTracker', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + customCoverFromTrackerIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'customCoverFromTracker', + value: '', + )); + }); + } + + QueryBuilder + customCoverFromTrackerIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'customCoverFromTracker', + value: '', + )); + }); + } + QueryBuilder customCoverImageIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( @@ -2448,6 +2619,18 @@ extension MangaQuerySortBy on QueryBuilder { }); } + QueryBuilder sortByCustomCoverFromTracker() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'customCoverFromTracker', Sort.asc); + }); + } + + QueryBuilder sortByCustomCoverFromTrackerDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'customCoverFromTracker', Sort.desc); + }); + } + QueryBuilder sortByDateAdded() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'dateAdded', Sort.asc); @@ -2618,6 +2801,18 @@ extension MangaQuerySortThenBy on QueryBuilder { }); } + QueryBuilder thenByCustomCoverFromTracker() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'customCoverFromTracker', Sort.asc); + }); + } + + QueryBuilder thenByCustomCoverFromTrackerDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'customCoverFromTracker', Sort.desc); + }); + } + QueryBuilder thenByDateAdded() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'dateAdded', Sort.asc); @@ -2801,6 +2996,14 @@ extension MangaQueryWhereDistinct on QueryBuilder { }); } + QueryBuilder distinctByCustomCoverFromTracker( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'customCoverFromTracker', + caseSensitive: caseSensitive); + }); + } + QueryBuilder distinctByCustomCoverImage() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'customCoverImage'); @@ -2917,6 +3120,13 @@ extension MangaQueryProperty on QueryBuilder { }); } + QueryBuilder + customCoverFromTrackerProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'customCoverFromTracker'); + }); + } + QueryBuilder?, QQueryOperations> customCoverImageProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'customCoverImage'); diff --git a/lib/modules/anime/providers/anime_player_controller_provider.g.dart b/lib/modules/anime/providers/anime_player_controller_provider.g.dart index e50bb2e7..fce6aaad 100644 --- a/lib/modules/anime/providers/anime_player_controller_provider.g.dart +++ b/lib/modules/anime/providers/anime_player_controller_provider.g.dart @@ -7,7 +7,7 @@ part of 'anime_player_controller_provider.dart'; // ************************************************************************** String _$animeStreamControllerHash() => - r'05102c5a067600752d15236c270f5eb1ab553980'; + r'bf0730758333f74352257fb6afd2d0d0a319044f'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/modules/browse/global_search/global_search_screen.dart b/lib/modules/browse/global_search/global_search_screen.dart index 68ede643..0167f643 100644 --- a/lib/modules/browse/global_search/global_search_screen.dart +++ b/lib/modules/browse/global_search/global_search_screen.dart @@ -235,7 +235,6 @@ class _MangaGlobalImageCardState extends ConsumerState Widget build(BuildContext context) { super.build(context); final getMangaDetail = widget.manga; - final l10n = l10nLocalizations(context)!; return GestureDetector( onTap: () async { pushToMangaReaderDetail( @@ -254,6 +253,7 @@ class _MangaGlobalImageCardState extends ConsumerState .sourceEqualTo(widget.source.name) .watch(fireImmediately: true), builder: (context, snapshot) { + final hasData = snapshot.hasData && snapshot.data!.isNotEmpty; return Padding( padding: const EdgeInsets.only(left: 10), child: Stack( @@ -261,26 +261,30 @@ class _MangaGlobalImageCardState extends ConsumerState SizedBox( width: 110, child: Column(children: [ - snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.customCoverImage != null - ? Image.memory(snapshot.data!.first.customCoverImage - as Uint8List) - : ClipRRect( + Builder( + builder: (context) { + if (hasData && + snapshot.data!.first.customCoverImage != null) { + return Image.memory(snapshot + .data!.first.customCoverImage as Uint8List); + } + return ClipRRect( borderRadius: BorderRadius.circular(5), child: cachedNetworkImage( headers: ref.watch(headersProvider( source: widget.source.name!, lang: widget.source.lang!)), - imageUrl: snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.imageUrl != null - ? toImgUrl(snapshot.data!.first.imageUrl!) - : toImgUrl(getMangaDetail.imageUrl!), + imageUrl: toImgUrl(hasData + ? snapshot.data!.first + .customCoverFromTracker ?? + snapshot.data!.first.imageUrl ?? + "" + : getMangaDetail.imageUrl!), width: 110, height: 150, - fit: BoxFit.fill), - ), + fit: BoxFit.fill)); + }, + ), BottomTextWidget( fontSize: 12.0, text: widget.manga.name!, @@ -293,33 +297,19 @@ class _MangaGlobalImageCardState extends ConsumerState Container( width: 110, height: 150, - color: snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.favorite! + color: hasData && snapshot.data!.first.favorite! ? Colors.black.withOpacity(0.7) : null, ), - if (snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.favorite!) + if (hasData && snapshot.data!.first.favorite!) Positioned( top: 0, left: 0, child: Padding( padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - color: primaryColor(context), - borderRadius: BorderRadius.circular(5)), - child: Padding( - padding: const EdgeInsets.all(2), - child: Text( - l10n.in_library, - style: const TextStyle(fontSize: 10), - ), - ), - ), - )), + child: Icon(Icons.collections_bookmark, + color: primaryColor(context)), + )) ], ), ); diff --git a/lib/modules/history/history_screen.dart b/lib/modules/history/history_screen.dart index 2cfbfe77..7c5bc330 100644 --- a/lib/modules/history/history_screen.dart +++ b/lib/modules/history/history_screen.dart @@ -12,6 +12,7 @@ import 'package:mangayomi/modules/history/providers/isar_providers.dart'; import 'package:mangayomi/modules/manga/reader/providers/push_router.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/utils/cached_network.dart'; +import 'package:mangayomi/utils/constant.dart'; import 'package:mangayomi/utils/date.dart'; import 'package:mangayomi/utils/headers.dart'; import 'package:mangayomi/modules/library/widgets/search_text_form_field.dart'; @@ -260,7 +261,9 @@ class _HistoryTabState extends ConsumerState { headers: ref.watch(headersProvider( source: manga.source!, lang: manga.lang!)), - imageUrl: manga.imageUrl!, + imageUrl: toImgUrl( + manga.customCoverFromTracker ?? + manga.imageUrl!), width: 60, height: 90, fit: BoxFit.cover), diff --git a/lib/modules/library/providers/library_state_provider.g.dart b/lib/modules/library/providers/library_state_provider.g.dart index bbc0d7cf..f433fee6 100644 --- a/lib/modules/library/providers/library_state_provider.g.dart +++ b/lib/modules/library/providers/library_state_provider.g.dart @@ -2374,7 +2374,7 @@ final isLongPressedMangaStateProvider = typedef _$IsLongPressedMangaState = AutoDisposeNotifier; String _$mangasSetIsReadStateHash() => - r'f283b6c15d908212b462a2dacbf776eeead863fe'; + r'8f86296f588a48747de625e0471048978ee9bdeb'; abstract class _$MangasSetIsReadState extends BuildlessAutoDisposeNotifier { @@ -2519,7 +2519,7 @@ class _MangasSetIsReadStateProviderElement } String _$mangasSetUnReadStateHash() => - r'198aba4f8eb504fc05dbd003e8eb5c4d12d31ff7'; + r'3413e731b2fd8476a4032d3e47b943ca12f25090'; abstract class _$MangasSetUnReadState extends BuildlessAutoDisposeNotifier { diff --git a/lib/modules/library/widgets/library_gridview_widget.dart b/lib/modules/library/widgets/library_gridview_widget.dart index e6860b0b..217797fe 100644 --- a/lib/modules/library/widgets/library_gridview_widget.dart +++ b/lib/modules/library/widgets/library_gridview_widget.dart @@ -64,7 +64,7 @@ class LibraryGridViewWidget extends StatelessWidget { ? MemoryImage(entry.customCoverImage as Uint8List) as ImageProvider : CachedNetworkImageProvider( - toImgUrl(entry.imageUrl!), + toImgUrl(entry.customCoverFromTracker ?? entry.imageUrl!), headers: ref.watch(headersProvider( source: entry.source!, lang: entry.lang!)), ), diff --git a/lib/modules/library/widgets/library_listview_widget.dart b/lib/modules/library/widgets/library_listview_widget.dart index 30fc8373..0e5e5964 100644 --- a/lib/modules/library/widgets/library_listview_widget.dart +++ b/lib/modules/library/widgets/library_listview_widget.dart @@ -99,7 +99,9 @@ class LibraryListViewWidget extends StatelessWidget { ? MemoryImage(entry.customCoverImage as Uint8List) as ImageProvider : CachedNetworkImageProvider( - toImgUrl(entry.imageUrl!), + toImgUrl( + entry.customCoverFromTracker ?? + entry.imageUrl!), headers: ref.watch(headersProvider( source: entry.source!, lang: entry.lang!)), diff --git a/lib/modules/manga/detail/manga_detail_view.dart b/lib/modules/manga/detail/manga_detail_view.dart index 4d3ee2bb..5faebddc 100644 --- a/lib/modules/manga/detail/manga_detail_view.dart +++ b/lib/modules/manga/detail/manga_detail_view.dart @@ -234,7 +234,9 @@ class _MangaDetailViewState extends ConsumerState headers: ref.watch(headersProvider( source: widget.manga!.source!, lang: widget.manga!.lang!)), - imageUrl: toImgUrl(widget.manga!.imageUrl!), + imageUrl: toImgUrl( + widget.manga!.customCoverFromTracker ?? + widget.manga!.imageUrl!), width: mediaWidth(context, 1), height: 300, fit: BoxFit.cover), @@ -1320,7 +1322,9 @@ class _MangaDetailViewState extends ConsumerState final imageProvider = widget.manga!.customCoverImage != null ? MemoryImage(widget.manga!.customCoverImage as Uint8List) as ImageProvider - : CachedNetworkImageProvider(toImgUrl(widget.manga!.imageUrl!), + : CachedNetworkImageProvider( + toImgUrl(widget.manga!.customCoverFromTracker ?? + widget.manga!.imageUrl!), headers: ref.watch(headersProvider( source: widget.manga!.source!, lang: widget.manga!.lang!))); return Padding( @@ -1506,23 +1510,91 @@ class _MangaDetailViewState extends ConsumerState right: 0, child: Row( children: [ - if (!isLocalArchive) - if (widget.manga!.customCoverImage != null) + Column( + children: [ + StreamBuilder( + stream: isar.trackPreferences + .filter() + .syncIdIsNotNull() + .watch(fireImmediately: true), + builder: (context, snapshot) { + List? entries = + snapshot.hasData ? snapshot.data! : []; + if (entries.isEmpty) { + return Container(); + } + return Column( + children: entries + .map((e) => Padding( + padding: const EdgeInsets.all(8.0), + child: MaterialButton( + padding: const EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10)), + onPressed: () async { + final trackSearch = + await trackersSearchraggableMenu( + context, + isManga: widget.manga!.isManga!, + track: Track( + status: + TrackStatus.planToRead, + syncId: e.syncId!, + title: widget.manga!.name!), + ) as TrackSearch?; + if (trackSearch != null) { + isar.writeTxnSync(() { + isar.mangas.putSync(widget + .manga! + ..customCoverFromTracker = + trackSearch.coverUrl); + }); + if (mounted) { + Navigator.pop(context); + } + } + }, + child: Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(10), + color: + trackInfos(e.syncId!).$3), + width: 45, + height: 50, + child: Image.asset( + trackInfos(e.syncId!).$1, + height: 30, + ), + ), + ), + )) + .toList(), + ); + }, + ), + PopupMenuButton( itemBuilder: (context) { return [ - const PopupMenuItem( - value: 0, child: Text("Delete")), - const PopupMenuItem( - value: 1, child: Text("Edit")), + if (widget.manga!.customCoverImage != null || + widget.manga!.customCoverFromTracker != + null) + PopupMenuItem( + value: 0, + child: Text(context.l10n.delete)), + PopupMenuItem( + value: 1, child: Text(context.l10n.edit)), ]; }, onSelected: (value) async { final manga = widget.manga!; if (value == 0) { isar.writeTxnSync(() { - isar.mangas - .putSync(manga..customCoverImage = null); + isar.mangas.putSync(manga + ..customCoverImage = null + ..customCoverFromTracker = null); }); } else if (value == 1) { FilePickerResult? result = @@ -1544,9 +1616,9 @@ class _MangaDetailViewState extends ConsumerState }); } } - } - if (mounted) { - Navigator.pop(context); + if (mounted) { + Navigator.pop(context); + } } }, child: const Padding( @@ -1555,51 +1627,22 @@ class _MangaDetailViewState extends ConsumerState child: Icon(Icons.edit_outlined)), ), ), - // IconButton( - // onPressed: () async { - // Uint8List? bytes; - // if (isLocalArchive) { - // bytes = - // widget.manga!.customCoverImage as Uint8List?; - // } - // await Share.shareXFiles([ - // XFile.fromData(bytes!, - // name: widget.manga!.name, - // mimeType: 'image/jpeg') - // ]); - // }, - // icon: const CircleAvatar(child: Icon(Icons.share))), - - if (isLocalArchive || - widget.manga!.customCoverImage == null) - IconButton( - onPressed: () async { - FilePickerResult? result = - await FilePicker.platform.pickFiles( - type: FileType.custom, - allowedExtensions: [ - 'png', - 'jpg', - 'jpeg' - ]); - if (result != null) { - if (result.files.first.size < 5000000) { - final manga = widget.manga!; - final customCoverImage = - File(result.files.first.path!) - .readAsBytesSync(); - isar.writeTxnSync(() { - isar.mangas.putSync(manga - ..customCoverImage = customCoverImage); - }); - if (mounted) { - Navigator.pop(context); - } - } - } - }, - icon: const CircleAvatar( - child: Icon(Icons.edit_outlined))), + // IconButton( + // onPressed: () async { + // Uint8List? bytes; + // if (isLocalArchive) { + // bytes = + // widget.manga!.customCoverImage as Uint8List?; + // } + // await Share.shareXFiles([ + // XFile.fromData(bytes!, + // name: widget.manga!.name, + // mimeType: 'image/jpeg') + // ]); + // }, + // icon: const CircleAvatar(child: Icon(Icons.share))), + ], + ), ], ), ) diff --git a/lib/modules/manga/detail/providers/update_manga_detail_providers.g.dart b/lib/modules/manga/detail/providers/update_manga_detail_providers.g.dart index 1c87c197..e98211d7 100644 --- a/lib/modules/manga/detail/providers/update_manga_detail_providers.g.dart +++ b/lib/modules/manga/detail/providers/update_manga_detail_providers.g.dart @@ -6,7 +6,7 @@ part of 'update_manga_detail_providers.dart'; // RiverpodGenerator // ************************************************************************** -String _$updateMangaDetailHash() => r'7c528575751a4c88f3ea80edc87973dd668fba6c'; +String _$updateMangaDetailHash() => r'753f7db14ba8284ede82e9c8baec4344b28acedb'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/modules/manga/detail/widgets/tracker_search_widget.dart b/lib/modules/manga/detail/widgets/tracker_search_widget.dart index 330ccb24..69dd06b2 100644 --- a/lib/modules/manga/detail/widgets/tracker_search_widget.dart +++ b/lib/modules/manga/detail/widgets/tracker_search_widget.dart @@ -229,17 +229,22 @@ trackersSearchraggableMenu(BuildContext context, borderRadius: const BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20))), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, + child: Column( children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: IconButton( - onPressed: () { - Navigator.pop(context); - }, - icon: const Icon(Icons.clear)), - ) + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: const Icon(Icons.clear)), + ) + ], + ), + const Divider() ], ), )), diff --git a/lib/modules/manga/reader/providers/reader_controller_provider.g.dart b/lib/modules/manga/reader/providers/reader_controller_provider.g.dart index 81184e30..3bd4ea55 100644 --- a/lib/modules/manga/reader/providers/reader_controller_provider.g.dart +++ b/lib/modules/manga/reader/providers/reader_controller_provider.g.dart @@ -169,7 +169,7 @@ class _CurrentIndexProviderElement Chapter get chapter => (origin as CurrentIndexProvider).chapter; } -String _$readerControllerHash() => r'e6191b82e9cbbe2856c4c46b407ccd5da9206c8e'; +String _$readerControllerHash() => r'0b60b5d4cafa82d45d1e180969af0b7c982b1f82'; abstract class _$ReaderController extends BuildlessAutoDisposeNotifier { late final Chapter chapter; diff --git a/lib/modules/widgets/manga_image_card_widget.dart b/lib/modules/widgets/manga_image_card_widget.dart index b626d40b..54372d5d 100644 --- a/lib/modules/widgets/manga_image_card_widget.dart +++ b/lib/modules/widgets/manga_image_card_widget.dart @@ -10,7 +10,6 @@ import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; import 'package:mangayomi/models/source.dart'; import 'package:mangayomi/modules/manga/detail/manga_detail_main.dart'; -import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/router/router.dart'; import 'package:mangayomi/utils/colors.dart'; import 'package:mangayomi/utils/constant.dart'; @@ -32,7 +31,6 @@ class MangaImageCardWidget extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final l10n = l10nLocalizations(context); return StreamBuilder( stream: isar.mangas .filter() @@ -41,19 +39,18 @@ class MangaImageCardWidget extends ConsumerWidget { .sourceEqualTo(source.name) .watch(fireImmediately: true), builder: (context, snapshot) { + final hasData = snapshot.hasData && snapshot.data!.isNotEmpty; return CoverViewWidget( - image: snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.customCoverImage != null + image: hasData && snapshot.data!.first.customCoverImage != null ? MemoryImage( snapshot.data!.first.customCoverImage as Uint8List) as ImageProvider : CachedNetworkImageProvider( - snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.imageUrl != null - ? toImgUrl(snapshot.data!.first.imageUrl!) - : toImgUrl(getMangaDetail!.imageUrl!), + toImgUrl(hasData + ? snapshot.data!.first.customCoverFromTracker ?? + snapshot.data!.first.imageUrl ?? + "" + : getMangaDetail!.imageUrl!), headers: ref.watch(headersProvider( source: source.name!, lang: source.lang!)), ), @@ -67,35 +64,18 @@ class MangaImageCardWidget extends ConsumerWidget { }, children: [ Container( - color: snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.favorite! - ? Colors.black.withOpacity(0.7) + color: hasData && snapshot.data!.first.favorite! + ? Colors.black.withOpacity(0.6) : null, ), - if (snapshot.hasData && - snapshot.data!.isNotEmpty && - snapshot.data!.first.favorite!) + if (hasData && snapshot.data!.first.favorite!) Positioned( top: 0, left: 0, child: Padding( padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - color: primaryColor(context), - borderRadius: BorderRadius.circular(5)), - child: Padding( - padding: const EdgeInsets.all(2), - child: Text( - l10n!.in_library, - style: TextStyle( - fontSize: 12, - color: Theme.of(context) - .scaffoldBackgroundColor), - ), - ), - ), + child: Icon(Icons.collections_bookmark, + color: primaryColor(context)), )), BottomTextWidget(text: getMangaDetail!.name!) ]); diff --git a/lib/services/trackers/kitsu.g.dart b/lib/services/trackers/kitsu.g.dart index b974dd8a..28e41f57 100644 --- a/lib/services/trackers/kitsu.g.dart +++ b/lib/services/trackers/kitsu.g.dart @@ -6,7 +6,7 @@ part of 'kitsu.dart'; // RiverpodGenerator // ************************************************************************** -String _$kitsuHash() => r'c6a31bcfb827bba5d0938d350538a01926d42297'; +String _$kitsuHash() => r'425a6699eafe84e35320c9a66bce33b4ba332a52'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/utils/headers.g.dart b/lib/utils/headers.g.dart index 5514ed0f..82e6473a 100644 --- a/lib/utils/headers.g.dart +++ b/lib/utils/headers.g.dart @@ -6,7 +6,7 @@ part of 'headers.dart'; // RiverpodGenerator // ************************************************************************** -String _$headersHash() => r'36e19ced66a55af45ef31bb3b342505246745ebe'; +String _$headersHash() => r'2075121328277856708a7f61718d22c409f915e0'; /// Copied from Dart SDK class _SystemHash {