From ee9e2a76cb46651696d37f53e68fafd2cd1c9b82 Mon Sep 17 00:00:00 2001 From: kodjomoustapha <107993382+kodjodevf@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:37:40 +0100 Subject: [PATCH] rename feed to update and make some arrangements --- lib/l10n/app_en.arb | 3 +- lib/models/{feed.dart => update.dart} | 10 +- lib/models/{feed.g.dart => update.g.dart} | 198 +++++------ lib/modules/feed/feed_screen.dart | 262 -------------- .../history/providers/isar_providers.dart | 6 +- .../history/providers/isar_providers.g.dart | 78 ++-- lib/modules/library/library_screen.dart | 37 +- lib/modules/main_view/main_screen.dart | 268 +++++++------- .../update_manga_detail_providers.dart | 8 +- .../update_manga_detail_providers.g.dart | 2 +- .../backup_and_restore/providers/restore.dart | 20 +- .../providers/restore.g.dart | 2 +- lib/modules/updates/updates_screen.dart | 332 +++++++++++++++++- .../update_chapter_list_tile_widget.dart} | 4 +- lib/providers/storage_provider.dart | 4 +- lib/router/router.dart | 20 +- lib/services/sync_server.dart | 44 +-- lib/services/sync_server.g.dart | 2 +- 18 files changed, 663 insertions(+), 637 deletions(-) rename lib/models/{feed.dart => update.dart} (84%) rename lib/models/{feed.g.dart => update.g.dart} (73%) delete mode 100644 lib/modules/feed/feed_screen.dart rename lib/modules/{feed/widgets/feed_chapter_list_tile_widget.dart => updates/widgets/update_chapter_list_tile_widget.dart} (97%) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ca3d84b..4cf4040 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -3,7 +3,6 @@ "library": "Library", "updates": "Updates", "history": "History", - "feed": "Feed", "browse": "Browse", "more": "More", "open_random_entry": "Open random entry", @@ -40,7 +39,7 @@ "no_recent_updates": "No recent updates", "remove_everything": "Remove everything", "remove_everything_msg": "Are you sure? All history will be lost", - "remove_all_feed_msg": "Are you sure? The whole feed will be cleared", + "remove_all_update_msg": "Are you sure? The whole update will be cleared", "ok": "OK", "cancel": "Cancel", "remove": "Remove", diff --git a/lib/models/feed.dart b/lib/models/update.dart similarity index 84% rename from lib/models/feed.dart rename to lib/models/update.dart index 909563c..c154969 100644 --- a/lib/models/feed.dart +++ b/lib/models/update.dart @@ -1,10 +1,10 @@ import 'package:isar/isar.dart'; import 'package:mangayomi/models/chapter.dart'; -part 'feed.g.dart'; +part 'update.g.dart'; @collection -@Name("Feed") -class Feed { +@Name("Update") +class Update { Id? id; int? mangaId; @@ -15,14 +15,14 @@ class Feed { String? date; - Feed({ + Update({ this.id = Isar.autoIncrement, required this.mangaId, required this.chapterName, required this.date, }); - Feed.fromJson(Map json) { + Update.fromJson(Map json) { id = json['id']; mangaId = json['mangaId']; chapterName = json['chapterName']; diff --git a/lib/models/feed.g.dart b/lib/models/update.g.dart similarity index 73% rename from lib/models/feed.g.dart rename to lib/models/update.g.dart index e8c8ce2..a543c87 100644 --- a/lib/models/feed.g.dart +++ b/lib/models/update.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'feed.dart'; +part of 'update.dart'; // ************************************************************************** // IsarCollectionGenerator @@ -9,13 +9,13 @@ part of 'feed.dart'; // coverage:ignore-file // ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types -extension GetFeedCollection on Isar { - IsarCollection get feeds => this.collection(); +extension GetUpdateCollection on Isar { + IsarCollection get updates => this.collection(); } -const FeedSchema = CollectionSchema( - name: r'Feed', - id: 8879644747771893978, +const UpdateSchema = CollectionSchema( + name: r'Update', + id: -8192355249181452821, properties: { r'chapterName': PropertySchema( id: 0, @@ -33,29 +33,29 @@ const FeedSchema = CollectionSchema( type: IsarType.long, ) }, - estimateSize: _feedEstimateSize, - serialize: _feedSerialize, - deserialize: _feedDeserialize, - deserializeProp: _feedDeserializeProp, + estimateSize: _updateEstimateSize, + serialize: _updateSerialize, + deserialize: _updateDeserialize, + deserializeProp: _updateDeserializeProp, idName: r'id', indexes: {}, links: { r'chapter': LinkSchema( - id: 8037684855892205613, + id: -7524967726288995715, name: r'chapter', target: r'Chapter', single: true, ) }, embeddedSchemas: {}, - getId: _feedGetId, - getLinks: _feedGetLinks, - attach: _feedAttach, + getId: _updateGetId, + getLinks: _updateGetLinks, + attach: _updateAttach, version: '3.1.0+1', ); -int _feedEstimateSize( - Feed object, +int _updateEstimateSize( + Update object, List offsets, Map> allOffsets, ) { @@ -75,8 +75,8 @@ int _feedEstimateSize( return bytesCount; } -void _feedSerialize( - Feed object, +void _updateSerialize( + Update object, IsarWriter writer, List offsets, Map> allOffsets, @@ -86,13 +86,13 @@ void _feedSerialize( writer.writeLong(offsets[2], object.mangaId); } -Feed _feedDeserialize( +Update _updateDeserialize( Id id, IsarReader reader, List offsets, Map> allOffsets, ) { - final object = Feed( + final object = Update( chapterName: reader.readStringOrNull(offsets[0]), date: reader.readStringOrNull(offsets[1]), id: id, @@ -101,7 +101,7 @@ Feed _feedDeserialize( return object; } -P _feedDeserializeProp

( +P _updateDeserializeProp

( IsarReader reader, int propertyId, int offset, @@ -119,29 +119,29 @@ P _feedDeserializeProp

( } } -Id _feedGetId(Feed object) { +Id _updateGetId(Update object) { return object.id ?? Isar.autoIncrement; } -List> _feedGetLinks(Feed object) { +List> _updateGetLinks(Update object) { return [object.chapter]; } -void _feedAttach(IsarCollection col, Id id, Feed object) { +void _updateAttach(IsarCollection col, Id id, Update object) { object.id = id; object.chapter.attach(col, col.isar.collection(), r'chapter', id); } -extension FeedQueryWhereSort on QueryBuilder { - QueryBuilder anyId() { +extension UpdateQueryWhereSort on QueryBuilder { + QueryBuilder anyId() { return QueryBuilder.apply(this, (query) { return query.addWhereClause(const IdWhereClause.any()); }); } } -extension FeedQueryWhere on QueryBuilder { - QueryBuilder idEqualTo(Id id) { +extension UpdateQueryWhere on QueryBuilder { + QueryBuilder idEqualTo(Id id) { return QueryBuilder.apply(this, (query) { return query.addWhereClause(IdWhereClause.between( lower: id, @@ -150,7 +150,7 @@ extension FeedQueryWhere on QueryBuilder { }); } - QueryBuilder idNotEqualTo(Id id) { + QueryBuilder idNotEqualTo(Id id) { return QueryBuilder.apply(this, (query) { if (query.whereSort == Sort.asc) { return query @@ -172,7 +172,7 @@ extension FeedQueryWhere on QueryBuilder { }); } - QueryBuilder idGreaterThan(Id id, + QueryBuilder idGreaterThan(Id id, {bool include = false}) { return QueryBuilder.apply(this, (query) { return query.addWhereClause( @@ -181,7 +181,7 @@ extension FeedQueryWhere on QueryBuilder { }); } - QueryBuilder idLessThan(Id id, + QueryBuilder idLessThan(Id id, {bool include = false}) { return QueryBuilder.apply(this, (query) { return query.addWhereClause( @@ -190,7 +190,7 @@ extension FeedQueryWhere on QueryBuilder { }); } - QueryBuilder idBetween( + QueryBuilder idBetween( Id lowerId, Id upperId, { bool includeLower = true, @@ -207,8 +207,8 @@ extension FeedQueryWhere on QueryBuilder { } } -extension FeedQueryFilter on QueryBuilder { - QueryBuilder chapterNameIsNull() { +extension UpdateQueryFilter on QueryBuilder { + QueryBuilder chapterNameIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( property: r'chapterName', @@ -216,7 +216,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameIsNotNull() { + QueryBuilder chapterNameIsNotNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNotNull( property: r'chapterName', @@ -224,7 +224,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameEqualTo( + QueryBuilder chapterNameEqualTo( String? value, { bool caseSensitive = true, }) { @@ -237,7 +237,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameGreaterThan( + QueryBuilder chapterNameGreaterThan( String? value, { bool include = false, bool caseSensitive = true, @@ -252,7 +252,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameLessThan( + QueryBuilder chapterNameLessThan( String? value, { bool include = false, bool caseSensitive = true, @@ -267,7 +267,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameBetween( + QueryBuilder chapterNameBetween( String? lower, String? upper, { bool includeLower = true, @@ -286,7 +286,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameStartsWith( + QueryBuilder chapterNameStartsWith( String value, { bool caseSensitive = true, }) { @@ -299,7 +299,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameEndsWith( + QueryBuilder chapterNameEndsWith( String value, { bool caseSensitive = true, }) { @@ -312,7 +312,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameContains( + QueryBuilder chapterNameContains( String value, {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { @@ -324,7 +324,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameMatches( + QueryBuilder chapterNameMatches( String pattern, {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { @@ -336,7 +336,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameIsEmpty() { + QueryBuilder chapterNameIsEmpty() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( property: r'chapterName', @@ -345,7 +345,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder chapterNameIsNotEmpty() { + QueryBuilder chapterNameIsNotEmpty() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.greaterThan( property: r'chapterName', @@ -354,7 +354,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateIsNull() { + QueryBuilder dateIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( property: r'date', @@ -362,7 +362,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateIsNotNull() { + QueryBuilder dateIsNotNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNotNull( property: r'date', @@ -370,7 +370,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateEqualTo( + QueryBuilder dateEqualTo( String? value, { bool caseSensitive = true, }) { @@ -383,7 +383,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateGreaterThan( + QueryBuilder dateGreaterThan( String? value, { bool include = false, bool caseSensitive = true, @@ -398,7 +398,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateLessThan( + QueryBuilder dateLessThan( String? value, { bool include = false, bool caseSensitive = true, @@ -413,7 +413,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateBetween( + QueryBuilder dateBetween( String? lower, String? upper, { bool includeLower = true, @@ -432,7 +432,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateStartsWith( + QueryBuilder dateStartsWith( String value, { bool caseSensitive = true, }) { @@ -445,7 +445,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateEndsWith( + QueryBuilder dateEndsWith( String value, { bool caseSensitive = true, }) { @@ -458,7 +458,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateContains(String value, + QueryBuilder dateContains(String value, {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.contains( @@ -469,7 +469,8 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateMatches(String pattern, + QueryBuilder dateMatches( + String pattern, {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.matches( @@ -480,7 +481,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateIsEmpty() { + QueryBuilder dateIsEmpty() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( property: r'date', @@ -489,7 +490,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder dateIsNotEmpty() { + QueryBuilder dateIsNotEmpty() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.greaterThan( property: r'date', @@ -498,7 +499,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder idIsNull() { + QueryBuilder idIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( property: r'id', @@ -506,7 +507,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder idIsNotNull() { + QueryBuilder idIsNotNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNotNull( property: r'id', @@ -514,7 +515,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder idEqualTo(Id? value) { + QueryBuilder idEqualTo(Id? value) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( property: r'id', @@ -523,7 +524,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder idGreaterThan( + QueryBuilder idGreaterThan( Id? value, { bool include = false, }) { @@ -536,7 +537,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder idLessThan( + QueryBuilder idLessThan( Id? value, { bool include = false, }) { @@ -549,7 +550,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder idBetween( + QueryBuilder idBetween( Id? lower, Id? upper, { bool includeLower = true, @@ -566,7 +567,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder mangaIdIsNull() { + QueryBuilder mangaIdIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( property: r'mangaId', @@ -574,7 +575,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder mangaIdIsNotNull() { + QueryBuilder mangaIdIsNotNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNotNull( property: r'mangaId', @@ -582,7 +583,8 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder mangaIdEqualTo(int? value) { + QueryBuilder mangaIdEqualTo( + int? value) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( property: r'mangaId', @@ -591,7 +593,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder mangaIdGreaterThan( + QueryBuilder mangaIdGreaterThan( int? value, { bool include = false, }) { @@ -604,7 +606,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder mangaIdLessThan( + QueryBuilder mangaIdLessThan( int? value, { bool include = false, }) { @@ -617,7 +619,7 @@ extension FeedQueryFilter on QueryBuilder { }); } - QueryBuilder mangaIdBetween( + QueryBuilder mangaIdBetween( int? lower, int? upper, { bool includeLower = true, @@ -635,153 +637,153 @@ extension FeedQueryFilter on QueryBuilder { } } -extension FeedQueryObject on QueryBuilder {} +extension UpdateQueryObject on QueryBuilder {} -extension FeedQueryLinks on QueryBuilder { - QueryBuilder chapter( +extension UpdateQueryLinks on QueryBuilder { + QueryBuilder chapter( FilterQuery q) { return QueryBuilder.apply(this, (query) { return query.link(q, r'chapter'); }); } - QueryBuilder chapterIsNull() { + QueryBuilder chapterIsNull() { return QueryBuilder.apply(this, (query) { return query.linkLength(r'chapter', 0, true, 0, true); }); } } -extension FeedQuerySortBy on QueryBuilder { - QueryBuilder sortByChapterName() { +extension UpdateQuerySortBy on QueryBuilder { + QueryBuilder sortByChapterName() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'chapterName', Sort.asc); }); } - QueryBuilder sortByChapterNameDesc() { + QueryBuilder sortByChapterNameDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'chapterName', Sort.desc); }); } - QueryBuilder sortByDate() { + QueryBuilder sortByDate() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'date', Sort.asc); }); } - QueryBuilder sortByDateDesc() { + QueryBuilder sortByDateDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'date', Sort.desc); }); } - QueryBuilder sortByMangaId() { + QueryBuilder sortByMangaId() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'mangaId', Sort.asc); }); } - QueryBuilder sortByMangaIdDesc() { + QueryBuilder sortByMangaIdDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'mangaId', Sort.desc); }); } } -extension FeedQuerySortThenBy on QueryBuilder { - QueryBuilder thenByChapterName() { +extension UpdateQuerySortThenBy on QueryBuilder { + QueryBuilder thenByChapterName() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'chapterName', Sort.asc); }); } - QueryBuilder thenByChapterNameDesc() { + QueryBuilder thenByChapterNameDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'chapterName', Sort.desc); }); } - QueryBuilder thenByDate() { + QueryBuilder thenByDate() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'date', Sort.asc); }); } - QueryBuilder thenByDateDesc() { + QueryBuilder thenByDateDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'date', Sort.desc); }); } - QueryBuilder thenById() { + QueryBuilder thenById() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'id', Sort.asc); }); } - QueryBuilder thenByIdDesc() { + QueryBuilder thenByIdDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'id', Sort.desc); }); } - QueryBuilder thenByMangaId() { + QueryBuilder thenByMangaId() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'mangaId', Sort.asc); }); } - QueryBuilder thenByMangaIdDesc() { + QueryBuilder thenByMangaIdDesc() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'mangaId', Sort.desc); }); } } -extension FeedQueryWhereDistinct on QueryBuilder { - QueryBuilder distinctByChapterName( +extension UpdateQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByChapterName( {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'chapterName', caseSensitive: caseSensitive); }); } - QueryBuilder distinctByDate( + QueryBuilder distinctByDate( {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'date', caseSensitive: caseSensitive); }); } - QueryBuilder distinctByMangaId() { + QueryBuilder distinctByMangaId() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'mangaId'); }); } } -extension FeedQueryProperty on QueryBuilder { - QueryBuilder idProperty() { +extension UpdateQueryProperty on QueryBuilder { + QueryBuilder idProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'id'); }); } - QueryBuilder chapterNameProperty() { + QueryBuilder chapterNameProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'chapterName'); }); } - QueryBuilder dateProperty() { + QueryBuilder dateProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'date'); }); } - QueryBuilder mangaIdProperty() { + QueryBuilder mangaIdProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'mangaId'); }); diff --git a/lib/modules/feed/feed_screen.dart b/lib/modules/feed/feed_screen.dart deleted file mode 100644 index 361384a..0000000 --- a/lib/modules/feed/feed_screen.dart +++ /dev/null @@ -1,262 +0,0 @@ -import 'package:flutter/material.dart'; -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/chapter.dart'; -import 'package:mangayomi/models/feed.dart'; -import 'package:mangayomi/models/history.dart'; -import 'package:mangayomi/models/manga.dart'; -import 'package:mangayomi/modules/feed/widgets/feed_chapter_list_tile_widget.dart'; -import 'package:mangayomi/modules/history/providers/isar_providers.dart'; -import 'package:mangayomi/providers/l10n_providers.dart'; -import 'package:mangayomi/utils/date.dart'; -import 'package:mangayomi/modules/library/widgets/search_text_form_field.dart'; -import 'package:mangayomi/modules/widgets/error_text.dart'; -import 'package:mangayomi/modules/widgets/progress_center.dart'; -import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; - -class FeedScreen extends ConsumerStatefulWidget { - const FeedScreen({super.key}); - - @override - ConsumerState createState() => _FeedScreenState(); -} - -class _FeedScreenState extends ConsumerState - with TickerProviderStateMixin { - late TabController _tabBarController; - - @override - void initState() { - _tabBarController = TabController(length: 2, vsync: this); - _tabBarController.animateTo(0); - _tabBarController.addListener(() { - setState(() { - _textEditingController.clear(); - _isSearch = false; - }); - }); - super.initState(); - } - - final _textEditingController = TextEditingController(); - bool _isSearch = false; - List entriesData = []; - @override - Widget build(BuildContext context) { - final l10n = l10nLocalizations(context)!; - return DefaultTabController( - animationDuration: Duration.zero, - length: 2, - child: Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: Colors.transparent, - title: _isSearch - ? null - : Text( - l10n.feed, - style: TextStyle(color: Theme.of(context).hintColor), - ), - actions: [ - _isSearch - ? SeachFormTextField( - onChanged: (value) { - setState(() {}); - }, - onSuffixPressed: () { - _textEditingController.clear(); - setState(() {}); - }, - onPressed: () { - setState(() { - _isSearch = false; - }); - _textEditingController.clear(); - }, - controller: _textEditingController, - ) - : IconButton( - splashRadius: 20, - onPressed: () { - setState(() { - _isSearch = true; - }); - }, - icon: - Icon(Icons.search, color: Theme.of(context).hintColor)), - IconButton( - splashRadius: 20, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text( - l10n.remove_everything, - ), - content: Text(l10n.remove_all_feed_msg), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text(l10n.cancel)), - const SizedBox( - width: 15, - ), - TextButton( - onPressed: () { - List feeds = isar.feeds - .filter() - .idIsNotNull() - .chapter((q) => q.manga((q) => - q.isMangaEqualTo( - _tabBarController.index == - 0))) - .findAllSync() - .toList(); - isar.writeTxnSync(() { - for (var feed in feeds) { - isar.feeds.deleteSync(feed.id!); - } - }); - if (mounted) { - Navigator.pop(context); - } - }, - child: Text(l10n.ok)), - ], - ) - ], - ); - }); - }, - icon: Icon(Icons.delete_sweep_outlined, - color: Theme.of(context).hintColor)), - ], - bottom: TabBar( - indicatorSize: TabBarIndicatorSize.tab, - controller: _tabBarController, - tabs: [ - Tab(text: l10n.manga), - Tab(text: l10n.anime), - ], - ), - ), - body: Padding( - padding: const EdgeInsets.only(top: 10), - child: TabBarView(controller: _tabBarController, children: [ - FeedTab( - isManga: true, - query: _textEditingController.text, - ), - FeedTab( - isManga: false, - query: _textEditingController.text, - ) - ]), - ), - ), - ); - } -} - -class FeedTab extends ConsumerStatefulWidget { - final String query; - final bool isManga; - const FeedTab({required this.isManga, required this.query, super.key}); - - @override - ConsumerState createState() => _FeedTabState(); -} - -class _FeedTabState extends ConsumerState { - @override - Widget build(BuildContext context) { - final l10n = l10nLocalizations(context)!; - final feed = ref.watch(getAllFeedStreamProvider(isManga: widget.isManga)); - return Scaffold( - body: feed.when( - data: (data) { - final entries = data - .where((element) => widget.query.isNotEmpty - ? element.chapter.value!.manga.value!.name! - .toLowerCase() - .contains(widget.query.toLowerCase()) - : true) - .toList(); - final lastUpdatedList = - data.map((e) => e.chapter.value!.manga.value!.lastUpdate!).toList(); - lastUpdatedList.sort((a, b) => a.compareTo(b)); - final lastUpdated = lastUpdatedList.firstOrNull; - if (entries.isNotEmpty) { - return CustomScrollView( - slivers: [ - if (lastUpdated != null) - SliverPadding( - padding: const EdgeInsets.only( - left: 10, right: 10, top: 10, bottom: 20), - sliver: SliverList( - delegate: SliverChildListDelegate.fixed([ - Text( - l10n.library_last_updated(dateFormat( - lastUpdated.toString(), - ref: ref, - context: context, - showHOURorMINUTE: true)), - style: TextStyle( - fontStyle: FontStyle.italic, - color: context.secondaryColor)) - ])), - ), - SliverGroupedListView( - elements: entries, - groupBy: (element) => dateFormat(element.date!, - context: context, - ref: ref, - forHistoryValue: true, - useRelativeTimesTamps: false), - groupSeparatorBuilder: (String groupByValue) => Padding( - padding: const EdgeInsets.only(bottom: 8, left: 12), - child: Row( - children: [ - Text(dateFormat( - null, - context: context, - stringDate: groupByValue, - ref: ref, - )), - ], - ), - ), - itemBuilder: (context, Feed element) { - final chapter = element.chapter.value!; - return FeedChapterListTileWidget( - chapter: chapter, sourceExist: true); - }, - itemComparator: (item1, item2) => - item1.date!.compareTo(item2.date!), - order: GroupedListOrder.DESC, - ), - ], - ); - } - return Center( - child: Text(l10n.no_recent_updates), - ); - }, - error: (Object error, StackTrace stackTrace) { - return ErrorText(error); - }, - loading: () { - return const ProgressCenter(); - }, - )); - } -} diff --git a/lib/modules/history/providers/isar_providers.dart b/lib/modules/history/providers/isar_providers.dart index a08b3b9..049f4a2 100644 --- a/lib/modules/history/providers/isar_providers.dart +++ b/lib/modules/history/providers/isar_providers.dart @@ -1,7 +1,7 @@ import 'package:isar/isar.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/chapter.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/models/history.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -19,9 +19,9 @@ Stream> getAllHistoryStream(GetAllHistoryStreamRef ref, } @riverpod -Stream> getAllFeedStream(GetAllFeedStreamRef ref, +Stream> getAllUpdateStream(GetAllUpdateStreamRef ref, {required bool isManga}) async* { - yield* isar.feeds + yield* isar.updates .filter() .idIsNotNull() .and() diff --git a/lib/modules/history/providers/isar_providers.g.dart b/lib/modules/history/providers/isar_providers.g.dart index f370b20..ba1149b 100644 --- a/lib/modules/history/providers/isar_providers.g.dart +++ b/lib/modules/history/providers/isar_providers.g.dart @@ -158,29 +158,30 @@ class _GetAllHistoryStreamProviderElement bool get isManga => (origin as GetAllHistoryStreamProvider).isManga; } -String _$getAllFeedStreamHash() => r'3d60bca5377bf6fc2aee36e7bec5b319b2377add'; +String _$getAllUpdateStreamHash() => + r'9f62b36ef0b268ee8c3cc93a10f8963def8dfbb0'; -/// See also [getAllFeedStream]. -@ProviderFor(getAllFeedStream) -const getAllFeedStreamProvider = GetAllFeedStreamFamily(); +/// See also [getAllUpdateStream]. +@ProviderFor(getAllUpdateStream) +const getAllUpdateStreamProvider = GetAllUpdateStreamFamily(); -/// See also [getAllFeedStream]. -class GetAllFeedStreamFamily extends Family>> { - /// See also [getAllFeedStream]. - const GetAllFeedStreamFamily(); +/// See also [getAllUpdateStream]. +class GetAllUpdateStreamFamily extends Family>> { + /// See also [getAllUpdateStream]. + const GetAllUpdateStreamFamily(); - /// See also [getAllFeedStream]. - GetAllFeedStreamProvider call({ + /// See also [getAllUpdateStream]. + GetAllUpdateStreamProvider call({ required bool isManga, }) { - return GetAllFeedStreamProvider( + return GetAllUpdateStreamProvider( isManga: isManga, ); } @override - GetAllFeedStreamProvider getProviderOverride( - covariant GetAllFeedStreamProvider provider, + GetAllUpdateStreamProvider getProviderOverride( + covariant GetAllUpdateStreamProvider provider, ) { return call( isManga: provider.isManga, @@ -199,32 +200,33 @@ class GetAllFeedStreamFamily extends Family>> { _allTransitiveDependencies; @override - String? get name => r'getAllFeedStreamProvider'; + String? get name => r'getAllUpdateStreamProvider'; } -/// See also [getAllFeedStream]. -class GetAllFeedStreamProvider extends AutoDisposeStreamProvider> { - /// See also [getAllFeedStream]. - GetAllFeedStreamProvider({ +/// See also [getAllUpdateStream]. +class GetAllUpdateStreamProvider + extends AutoDisposeStreamProvider> { + /// See also [getAllUpdateStream]. + GetAllUpdateStreamProvider({ required bool isManga, }) : this._internal( - (ref) => getAllFeedStream( - ref as GetAllFeedStreamRef, + (ref) => getAllUpdateStream( + ref as GetAllUpdateStreamRef, isManga: isManga, ), - from: getAllFeedStreamProvider, - name: r'getAllFeedStreamProvider', + from: getAllUpdateStreamProvider, + name: r'getAllUpdateStreamProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') ? null - : _$getAllFeedStreamHash, - dependencies: GetAllFeedStreamFamily._dependencies, + : _$getAllUpdateStreamHash, + dependencies: GetAllUpdateStreamFamily._dependencies, allTransitiveDependencies: - GetAllFeedStreamFamily._allTransitiveDependencies, + GetAllUpdateStreamFamily._allTransitiveDependencies, isManga: isManga, ); - GetAllFeedStreamProvider._internal( + GetAllUpdateStreamProvider._internal( super._createNotifier, { required super.name, required super.dependencies, @@ -238,12 +240,12 @@ class GetAllFeedStreamProvider extends AutoDisposeStreamProvider> { @override Override overrideWith( - Stream> Function(GetAllFeedStreamRef provider) create, + Stream> Function(GetAllUpdateStreamRef provider) create, ) { return ProviderOverride( origin: this, - override: GetAllFeedStreamProvider._internal( - (ref) => create(ref as GetAllFeedStreamRef), + override: GetAllUpdateStreamProvider._internal( + (ref) => create(ref as GetAllUpdateStreamRef), from: from, name: null, dependencies: null, @@ -255,13 +257,13 @@ class GetAllFeedStreamProvider extends AutoDisposeStreamProvider> { } @override - AutoDisposeStreamProviderElement> createElement() { - return _GetAllFeedStreamProviderElement(this); + AutoDisposeStreamProviderElement> createElement() { + return _GetAllUpdateStreamProviderElement(this); } @override bool operator ==(Object other) { - return other is GetAllFeedStreamProvider && other.isManga == isManga; + return other is GetAllUpdateStreamProvider && other.isManga == isManga; } @override @@ -273,18 +275,18 @@ class GetAllFeedStreamProvider extends AutoDisposeStreamProvider> { } } -mixin GetAllFeedStreamRef on AutoDisposeStreamProviderRef> { +mixin GetAllUpdateStreamRef on AutoDisposeStreamProviderRef> { /// The parameter `isManga` of this provider. bool get isManga; } -class _GetAllFeedStreamProviderElement - extends AutoDisposeStreamProviderElement> - with GetAllFeedStreamRef { - _GetAllFeedStreamProviderElement(super.provider); +class _GetAllUpdateStreamProviderElement + extends AutoDisposeStreamProviderElement> + with GetAllUpdateStreamRef { + _GetAllUpdateStreamProviderElement(super.provider); @override - bool get isManga => (origin as GetAllFeedStreamProvider).isManga; + bool get isManga => (origin as GetAllUpdateStreamProvider).isManga; } // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/modules/library/library_screen.dart b/lib/modules/library/library_screen.dart index 89985dd..5510281 100644 --- a/lib/modules/library/library_screen.dart +++ b/lib/modules/library/library_screen.dart @@ -16,7 +16,7 @@ import 'package:mangayomi/models/download.dart'; import 'package:mangayomi/models/history.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/modules/library/providers/add_torrent.dart'; import 'package:mangayomi/modules/library/providers/local_archive.dart'; import 'package:mangayomi/modules/manga/detail/providers/update_manga_detail_providers.dart'; @@ -59,26 +59,21 @@ class _LibraryScreenState extends ConsumerState botToast(context.l10n.updating_library, fontSize: 13, second: 1600, alignY: 0.8); int numbers = 0; - try { - for (var manga in mangaList) { - ref - .watch(updateMangaDetailProvider(mangaId: manga.id, isInit: false) - .future) - .then((value) { - numbers++; - }); - } - await Future.doWhile(() async { - await Future.delayed(const Duration(seconds: 1)); - if (mangaList.length == numbers) { - return false; - } - return true; - }); - BotToast.cleanAll(); - } catch (e) { - BotToast.cleanAll(); + for (var manga in mangaList) { + try { + await ref.read( + updateMangaDetailProvider(mangaId: manga.id, isInit: false).future); + } catch (_) {} + numbers++; } + await Future.doWhile(() async { + await Future.delayed(const Duration(seconds: 1)); + if (mangaList.length == numbers) { + return false; + } + return true; + }); + BotToast.cleanAll(); } @override @@ -1165,7 +1160,7 @@ class _LibraryScreenState extends ConsumerState .notifier) .addUpdatedChapter( chapter, true, false); - isar.feeds + isar.updates .filter() .mangaIdEqualTo(chapter.mangaId) .chapterNameEqualTo(chapter.name) diff --git a/lib/modules/main_view/main_screen.dart b/lib/modules/main_view/main_screen.dart index 7f86bce..c6e5122 100644 --- a/lib/modules/main_view/main_screen.dart +++ b/lib/modules/main_view/main_screen.dart @@ -5,7 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:isar/isar.dart'; import 'package:mangayomi/main.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/models/source.dart'; import 'package:mangayomi/modules/widgets/loading_icon.dart'; import 'package:mangayomi/services/fetch_anime_sources.dart'; @@ -42,11 +42,10 @@ class MainScreen extends ConsumerWidget { bool isReadingScreen = location == '/mangareaderview' || location == '/animePlayerView'; int currentIndex = switch (location) { - null => 0, - '/MangaLibrary' => 0, + null || '/MangaLibrary' => 0, '/AnimeLibrary' => 1, - '/history' => 2, - '/feed' => 3, + '/updates' => 2, + '/history' => 3, '/browse' => 4, _ => 5, }; @@ -98,7 +97,7 @@ class MainScreen extends ConsumerWidget { != '/MangaLibrary' && != '/AnimeLibrary' && != '/history' && - != '/feed' && + != '/updates' && != '/browse' && != '/more' => 0, @@ -113,103 +112,112 @@ class MainScreen extends ConsumerWidget { borderRadius: BorderRadius.circular(30)), ), - child: NavigationRail( - labelType: NavigationRailLabelType.all, - useIndicator: true, - destinations: [ - NavigationRailDestination( - selectedIcon: const Icon( - Icons.collections_bookmark), - icon: const Icon(Icons - .collections_bookmark_outlined), - label: Padding( - padding: - const EdgeInsets.only(top: 5), - child: Text(l10n.manga))), - NavigationRailDestination( - selectedIcon: const Icon( - Icons.video_collection), - icon: const Icon( - Icons.video_collection_outlined), - label: Padding( - padding: - const EdgeInsets.only(top: 5), - child: Text(l10n.anime))), - NavigationRailDestination( - selectedIcon: - const Icon(Icons.history), - icon: const Icon( - Icons.history_outlined), - label: Padding( - padding: - const EdgeInsets.only(top: 5), - child: Text(l10n.history))), - NavigationRailDestination( - selectedIcon: Stack( - children: [ - const Icon(Icons.rss_feed), - Positioned( - right: 0, - top: 0, - child: _feedTotalNumbers( - ref, false)) - ], - ), - icon: Stack( - children: [ - const Icon( - Icons.rss_feed_outlined), - Positioned( - right: 0, - top: 0, - child: _feedTotalNumbers( - ref, false)) - ], - ), - label: Padding( - padding: - const EdgeInsets.only(top: 5), - child: Stack( - children: [ - Text(l10n.feed), - ], - ))), - NavigationRailDestination( - selectedIcon: - const Icon(Icons.explore), - icon: const Icon( - Icons.explore_outlined), - label: Padding( - padding: - const EdgeInsets.only(top: 5), - child: Text(l10n.browse))), - NavigationRailDestination( - selectedIcon: - const Icon(Icons.more_horiz), - icon: const Icon( - Icons.more_horiz_outlined), - label: Padding( - padding: - const EdgeInsets.only(top: 5), - child: Text(l10n.more))), - ], - selectedIndex: currentIndex, - onDestinationSelected: (newIndex) { - if (newIndex == 0) { - route.go('/MangaLibrary'); - } else if (newIndex == 1) { - route.go('/AnimeLibrary'); - } else if (newIndex == 2) { - route.go('/history'); - } else if (newIndex == 3) { - route.go('/feed'); - } else if (newIndex == 4) { - route.go('/browse'); - } else if (newIndex == 5) { - route.go('/more'); - } - }, - ), + child: Builder(builder: (context) { + final updatesTotalNumbersWidget = Positioned( + right: 0, + top: 0, + child: _updatesTotalNumbers(ref, false)); + final extensionUpdateTotalNumbersWidget = + Positioned( + right: 0, + top: 0, + child: _extensionUpdateTotalNumbers( + ref)); + return NavigationRail( + labelType: NavigationRailLabelType.all, + useIndicator: true, + destinations: [ + NavigationRailDestination( + selectedIcon: const Icon( + Icons.collections_bookmark), + icon: const Icon(Icons + .collections_bookmark_outlined), + label: Padding( + padding: const EdgeInsets.only( + top: 5), + child: Text(l10n.manga))), + NavigationRailDestination( + selectedIcon: const Icon( + Icons.video_collection), + icon: const Icon(Icons + .video_collection_outlined), + label: Padding( + padding: const EdgeInsets.only( + top: 5), + child: Text(l10n.anime))), + NavigationRailDestination( + selectedIcon: Stack( + children: [ + const Icon(Icons.new_releases), + updatesTotalNumbersWidget + ], + ), + icon: Stack( + children: [ + const Icon(Icons + .new_releases_outlined), + updatesTotalNumbersWidget + ], + ), + label: Padding( + padding: const EdgeInsets.only( + top: 5), + child: Stack( + children: [ + Text(l10n.updates), + ], + ))), + NavigationRailDestination( + selectedIcon: + const Icon(Icons.history), + icon: const Icon( + Icons.history_outlined), + label: Padding( + padding: const EdgeInsets.only( + top: 5), + child: Text(l10n.history))), + NavigationRailDestination( + selectedIcon: Stack( + children: [ + const Icon(Icons.explore), + extensionUpdateTotalNumbersWidget + ], + ), + icon: Stack( + children: [ + const Icon( + Icons.explore_outlined), + extensionUpdateTotalNumbersWidget + ], + ), + label: Padding( + padding: const EdgeInsets.only( + top: 5), + child: Text(l10n.browse))), + NavigationRailDestination( + selectedIcon: + const Icon(Icons.more_horiz), + icon: const Icon( + Icons.more_horiz_outlined), + label: Padding( + padding: const EdgeInsets.only( + top: 5), + child: Text(l10n.more))), + ], + selectedIndex: currentIndex, + onDestinationSelected: (newIndex) { + final fn = switch (newIndex) { + 0 => route.go('/MangaLibrary'), + 1 => route.go('/AnimeLibrary'), + 2 => route.go('/updates'), + 3 => route.go('/history'), + 4 => route.go('/browse'), + _ => route.go('/more'), + }; + fn; + }, + ); + }), ), Positioned( right: 18, @@ -234,7 +242,7 @@ class MainScreen extends ConsumerWidget { != '/MangaLibrary' && != '/AnimeLibrary' && != '/history' && - != '/feed' && + != '/updates' && != '/browse' && != '/more' => 0, @@ -263,22 +271,24 @@ class MainScreen extends ConsumerWidget { icon: const Icon( Icons.video_collection_outlined), label: l10n.anime), + Stack( + children: [ + NavigationDestination( + selectedIcon: + const Icon(Icons.new_releases), + icon: const Icon( + Icons.new_releases_outlined), + label: l10n.updates), + Positioned( + right: 14, + top: 3, + child: _updatesTotalNumbers(ref, true)), + ], + ), NavigationDestination( selectedIcon: const Icon(Icons.history), icon: const Icon(Icons.history_outlined), label: l10n.history), - Stack( - children: [ - NavigationDestination( - selectedIcon: const Icon(Icons.rss_feed), - icon: const Icon(Icons.rss_feed_outlined), - label: l10n.feed), - Positioned( - right: 14, - top: 3, - child: _feedTotalNumbers(ref, true)), - ], - ), Stack( children: [ NavigationDestination( @@ -297,19 +307,15 @@ class MainScreen extends ConsumerWidget { label: l10n.more), ], onDestinationSelected: (newIndex) { - if (newIndex == 0) { - route.go('/MangaLibrary'); - } else if (newIndex == 1) { - route.go('/AnimeLibrary'); - } else if (newIndex == 2) { - route.go('/history'); - } else if (newIndex == 3) { - route.go('/feed'); - } else if (newIndex == 4) { - route.go('/browse'); - } else if (newIndex == 5) { - route.go('/more'); - } + final fn = switch (newIndex) { + 0 => route.go('/MangaLibrary'), + 1 => route.go('/AnimeLibrary'), + 2 => route.go('/updates'), + 3 => route.go('/history'), + 4 => route.go('/browse'), + _ => route.go('/more'), + }; + fn; }, ), ), @@ -366,9 +372,9 @@ Widget _extensionUpdateTotalNumbers(WidgetRef ref) { }); } -Widget _feedTotalNumbers(WidgetRef ref, bool mobile) { +Widget _updatesTotalNumbers(WidgetRef ref, bool mobile) { return StreamBuilder( - stream: isar.feeds.filter().idIsNotNull().watch(fireImmediately: true), + stream: isar.updates.filter().idIsNotNull().watch(fireImmediately: true), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data!.isNotEmpty) { final entries = snapshot.data!.where((element) { diff --git a/lib/modules/manga/detail/providers/update_manga_detail_providers.dart b/lib/modules/manga/detail/providers/update_manga_detail_providers.dart index 1c93e11..26f2426 100644 --- a/lib/modules/manga/detail/providers/update_manga_detail_providers.dart +++ b/lib/modules/manga/detail/providers/update_manga_detail_providers.dart @@ -2,7 +2,7 @@ import 'package:mangayomi/eval/dart/model/m_bridge.dart'; import 'package:mangayomi/eval/dart/model/m_manga.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/chapter.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart'; import 'package:mangayomi/services/get_detail.dart'; @@ -85,13 +85,13 @@ Future updateMangaDetail(UpdateMangaDetailRef ref, isar.chapters.putSync(chap); chap.manga.saveSync(); if (manga.chapters.isNotEmpty) { - final feed = Feed( + final update = Update( mangaId: mangaId, chapterName: chap.name, date: DateTime.now().millisecondsSinceEpoch.toString()) ..chapter.value = chap; - isar.feeds.putSync(feed); - feed.chapter.saveSync(); + isar.updates.putSync(update); + update.chapter.saveSync(); } } } 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 752197d..0224ad0 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'f72eb5e66fd9fb7ed61aa08365e068d77737438d'; +String _$updateMangaDetailHash() => r'736b68c65f624da85b15c0a7a2a263aab8e8df7e'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/modules/more/backup_and_restore/providers/restore.dart b/lib/modules/more/backup_and_restore/providers/restore.dart index 8aab257..97f26a2 100644 --- a/lib/modules/more/backup_and_restore/providers/restore.dart +++ b/lib/modules/more/backup_and_restore/providers/restore.dart @@ -9,7 +9,7 @@ import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/category.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/download.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/models/history.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; @@ -61,8 +61,8 @@ void doRestore(DoRestoreRef ref, final extensionsPref = (backup["extensions_preferences"] as List?) ?.map((e) => SourcePreference.fromJson(e)) .toList(); - final feeds = - (backup["feeds"] as List?)?.map((e) => Feed.fromJson(e)).toList(); + final updates = + (backup["updates"] as List?)?.map((e) => Update.fromJson(e)).toList(); isar.writeTxnSync(() { isar.mangas.clearSync(); @@ -100,19 +100,19 @@ void doRestore(DoRestoreRef ref, } } - isar.feeds.clearSync(); - if (feeds != null) { + isar.updates.clearSync(); + if (updates != null) { final tempChapters = isar.chapters.filter().idIsNotNull().findAllSync().toList(); - for (var feed in feeds) { + for (var update in updates) { final matchingChapter = tempChapters .where((chapter) => - chapter.mangaId == feed.mangaId && - chapter.name == feed.chapterName) + chapter.mangaId == update.mangaId && + chapter.name == update.chapterName) .firstOrNull; if (matchingChapter != null) { - isar.feeds.putSync(feed..chapter.value = matchingChapter); - feed.chapter.saveSync(); + isar.updates.putSync(update..chapter.value = matchingChapter); + update.chapter.saveSync(); } } } diff --git a/lib/modules/more/backup_and_restore/providers/restore.g.dart b/lib/modules/more/backup_and_restore/providers/restore.g.dart index d14af08..c6deccc 100644 --- a/lib/modules/more/backup_and_restore/providers/restore.g.dart +++ b/lib/modules/more/backup_and_restore/providers/restore.g.dart @@ -6,7 +6,7 @@ part of 'restore.dart'; // RiverpodGenerator // ************************************************************************** -String _$doRestoreHash() => r'823b26bade20d89ae7b7b56a7eb7c25020795b45'; +String _$doRestoreHash() => r'69153ba0467229d219346aab9e6ec87c52f66095'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/modules/updates/updates_screen.dart b/lib/modules/updates/updates_screen.dart index 00d0153..0796358 100644 --- a/lib/modules/updates/updates_screen.dart +++ b/lib/modules/updates/updates_screen.dart @@ -1,30 +1,324 @@ +import 'package:bot_toast/bot_toast.dart'; import 'package:flutter/material.dart'; -import 'package:mangayomi/providers/l10n_providers.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:grouped_list/sliver_grouped_list.dart'; -class UpdatesScreen extends StatelessWidget { +import 'package:isar/isar.dart'; +import 'package:mangayomi/eval/dart/model/m_bridge.dart'; +import 'package:mangayomi/main.dart'; +import 'package:mangayomi/models/chapter.dart'; +import 'package:mangayomi/models/update.dart'; +import 'package:mangayomi/models/history.dart'; +import 'package:mangayomi/models/manga.dart'; +import 'package:mangayomi/modules/manga/detail/providers/update_manga_detail_providers.dart'; +import 'package:mangayomi/modules/updates/widgets/update_chapter_list_tile_widget.dart'; +import 'package:mangayomi/modules/history/providers/isar_providers.dart'; +import 'package:mangayomi/providers/l10n_providers.dart'; +import 'package:mangayomi/utils/date.dart'; +import 'package:mangayomi/modules/library/widgets/search_text_form_field.dart'; +import 'package:mangayomi/modules/widgets/error_text.dart'; +import 'package:mangayomi/modules/widgets/progress_center.dart'; +import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; + +class UpdatesScreen extends ConsumerStatefulWidget { const UpdatesScreen({super.key}); + @override + ConsumerState createState() => _UpdatesScreenState(); +} + +class _UpdatesScreenState extends ConsumerState + with TickerProviderStateMixin { + late TabController _tabBarController; + bool _isLoading = false; + Future _updateLibrary() async { + setState(() { + _isLoading = true; + }); + botToast(context.l10n.updating_library, + fontSize: 13, second: 1600, alignY: 0.8); + final mangaList = + isar.mangas.filter().idIsNotNull().favoriteEqualTo(true).findAllSync(); + int numbers = 0; + + for (var manga in mangaList) { + try { + await ref.read( + updateMangaDetailProvider(mangaId: manga.id, isInit: false).future); + } catch (_) {} + numbers++; + } + await Future.doWhile(() async { + await Future.delayed(const Duration(seconds: 1)); + if (mangaList.length == numbers) { + return false; + } + return true; + }); + BotToast.cleanAll(); + setState(() { + _isLoading = false; + }); + } + + @override + void initState() { + _tabBarController = TabController(length: 2, vsync: this); + _tabBarController.animateTo(0); + _tabBarController.addListener(() { + setState(() { + _textEditingController.clear(); + _isSearch = false; + }); + }); + super.initState(); + } + + final _textEditingController = TextEditingController(); + bool _isSearch = false; + List entriesData = []; @override Widget build(BuildContext context) { - final l10n = l10nLocalizations(context); - return Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: Colors.transparent, - title: Text( - l10n!.updates, - style: TextStyle(color: Theme.of(context).hintColor), + final l10n = l10nLocalizations(context)!; + return DefaultTabController( + animationDuration: Duration.zero, + length: 2, + child: Scaffold( + appBar: AppBar( + elevation: 0, + backgroundColor: Colors.transparent, + title: _isSearch + ? null + : Text( + l10n.updates, + style: TextStyle(color: Theme.of(context).hintColor), + ), + actions: [ + _isSearch + ? SeachFormTextField( + onChanged: (value) { + setState(() {}); + }, + onSuffixPressed: () { + _textEditingController.clear(); + setState(() {}); + }, + onPressed: () { + setState(() { + _isSearch = false; + }); + _textEditingController.clear(); + }, + controller: _textEditingController, + ) + : IconButton( + splashRadius: 20, + onPressed: () { + setState(() { + _isSearch = true; + }); + }, + icon: Icon(Icons.search_outlined, + color: Theme.of(context).hintColor)), + IconButton( + splashRadius: 20, + onPressed: () { + _updateLibrary(); + }, + icon: Icon(Icons.refresh_outlined, + color: Theme.of(context).hintColor)), + IconButton( + splashRadius: 20, + onPressed: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text( + l10n.remove_everything, + ), + content: Text(l10n.remove_all_update_msg), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text(l10n.cancel)), + const SizedBox( + width: 15, + ), + TextButton( + onPressed: () { + List updates = isar.updates + .filter() + .idIsNotNull() + .chapter((q) => q.manga((q) => + q.isMangaEqualTo( + _tabBarController.index == + 0))) + .findAllSync() + .toList(); + isar.writeTxnSync(() { + for (var update in updates) { + isar.updates.deleteSync(update.id!); + } + }); + if (mounted) { + Navigator.pop(context); + } + }, + child: Text(l10n.ok)), + ], + ) + ], + ); + }); + }, + icon: Icon(Icons.delete_sweep_outlined, + color: Theme.of(context).hintColor)), + ], + bottom: TabBar( + indicatorSize: TabBarIndicatorSize.tab, + controller: _tabBarController, + tabs: [ + Tab(text: l10n.manga), + Tab(text: l10n.anime), + ], + ), + ), + body: Padding( + padding: const EdgeInsets.only(top: 10), + child: TabBarView(controller: _tabBarController, children: [ + UpdateTab( + isManga: true, + query: _textEditingController.text, + isLoading: _isLoading), + UpdateTab( + isManga: false, + query: _textEditingController.text, + isLoading: _isLoading) + ]), ), - actions: [ - IconButton( - splashRadius: 20, - onPressed: () {}, - icon: Icon(Icons.refresh, color: Theme.of(context).hintColor)), - ], - ), - body: Center( - child: Text(l10n.no_recent_updates), ), ); } } + +class UpdateTab extends ConsumerStatefulWidget { + final String query; + final bool isManga; + final bool isLoading; + const UpdateTab( + {required this.isManga, + required this.query, + required this.isLoading, + super.key}); + + @override + ConsumerState createState() => _UpdateTabState(); +} + +class _UpdateTabState extends ConsumerState { + @override + Widget build(BuildContext context) { + final l10n = l10nLocalizations(context)!; + final update = + ref.watch(getAllUpdateStreamProvider(isManga: widget.isManga)); + return Scaffold( + body: Stack( + children: [ + update.when( + data: (data) { + final entries = data + .where((element) => widget.query.isNotEmpty + ? element.chapter.value!.manga.value!.name! + .toLowerCase() + .contains(widget.query.toLowerCase()) + : true) + .toList(); + final lastUpdatedList = data + .map((e) => e.chapter.value!.manga.value!.lastUpdate!) + .toList(); + lastUpdatedList.sort((a, b) => a.compareTo(b)); + final lastUpdated = lastUpdatedList.firstOrNull; + if (entries.isNotEmpty) { + return CustomScrollView( + slivers: [ + if (lastUpdated != null) + SliverPadding( + padding: const EdgeInsets.only( + left: 10, right: 10, top: 10, bottom: 20), + sliver: SliverList( + delegate: SliverChildListDelegate.fixed([ + Text( + l10n.library_last_updated(dateFormat( + lastUpdated.toString(), + ref: ref, + context: context, + showHOURorMINUTE: true)), + style: TextStyle( + fontStyle: FontStyle.italic, + color: context.secondaryColor)) + ])), + ), + SliverGroupedListView( + elements: entries, + groupBy: (element) => dateFormat(element.date!, + context: context, + ref: ref, + forHistoryValue: true, + useRelativeTimesTamps: false), + groupSeparatorBuilder: (String groupByValue) => Padding( + padding: const EdgeInsets.only(bottom: 8, left: 12), + child: Row( + children: [ + Text(dateFormat( + null, + context: context, + stringDate: groupByValue, + ref: ref, + )), + ], + ), + ), + itemBuilder: (context, element) { + final chapter = element.chapter.value!; + return UpdateChapterListTileWidget( + chapter: chapter, sourceExist: true); + }, + itemComparator: (item1, item2) => + item1.date!.compareTo(item2.date!), + order: GroupedListOrder.DESC, + ), + ], + ); + } + return Center( + child: Text(l10n.no_recent_updates), + ); + }, + error: (Object error, StackTrace stackTrace) { + return ErrorText(error); + }, + loading: () { + return const ProgressCenter(); + }, + ), + if (widget.isLoading) + const Positioned( + top: 0, + left: 0, + right: 0, + child: Padding( + padding: EdgeInsets.only(top: 40), + child: Center( + child: RefreshProgressIndicator(), + ), + )), + ], + )); + } +} diff --git a/lib/modules/feed/widgets/feed_chapter_list_tile_widget.dart b/lib/modules/updates/widgets/update_chapter_list_tile_widget.dart similarity index 97% rename from lib/modules/feed/widgets/feed_chapter_list_tile_widget.dart rename to lib/modules/updates/widgets/update_chapter_list_tile_widget.dart index fec2ea6..1c7d281 100644 --- a/lib/modules/feed/widgets/feed_chapter_list_tile_widget.dart +++ b/lib/modules/updates/widgets/update_chapter_list_tile_widget.dart @@ -10,10 +10,10 @@ import 'package:mangayomi/modules/manga/download/download_page_widget.dart'; import 'package:mangayomi/utils/extensions/chapter.dart'; import 'package:mangayomi/utils/headers.dart'; -class FeedChapterListTileWidget extends ConsumerWidget { +class UpdateChapterListTileWidget extends ConsumerWidget { final Chapter chapter; final bool sourceExist; - const FeedChapterListTileWidget({ + const UpdateChapterListTileWidget({ required this.chapter, required this.sourceExist, super.key, diff --git a/lib/providers/storage_provider.dart b/lib/providers/storage_provider.dart index 7260a06..6bff6af 100644 --- a/lib/providers/storage_provider.dart +++ b/lib/providers/storage_provider.dart @@ -7,7 +7,7 @@ import 'package:mangayomi/models/category.dart'; import 'package:mangayomi/models/changed_items.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/download.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/models/history.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/models/settings.dart'; @@ -132,7 +132,7 @@ class StorageProvider { ChangedItemsSchema, ChapterSchema, CategorySchema, - FeedSchema, + UpdateSchema, HistorySchema, DownloadSchema, SourceSchema, diff --git a/lib/router/router.dart b/lib/router/router.dart index d056590..2394522 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -10,7 +10,7 @@ import 'package:mangayomi/modules/browse/extension/edit_code.dart'; import 'package:mangayomi/modules/browse/extension/extension_detail.dart'; import 'package:mangayomi/modules/browse/extension/widgets/create_extension.dart'; import 'package:mangayomi/modules/browse/sources/sources_filter_screen.dart'; -import 'package:mangayomi/modules/feed/feed_screen.dart'; +import 'package:mangayomi/modules/updates/updates_screen.dart'; import 'package:mangayomi/modules/more/backup_and_restore/backup_and_restore.dart'; import 'package:mangayomi/modules/more/categories/categories_screen.dart'; import 'package:mangayomi/modules/more/settings/downloads/downloads_screen.dart'; @@ -19,7 +19,6 @@ import 'package:mangayomi/modules/more/settings/sync/sync.dart'; import 'package:mangayomi/modules/more/settings/track/track.dart'; import 'package:mangayomi/modules/more/settings/track/manage_trackers/manage_trackers.dart'; import 'package:mangayomi/modules/more/settings/track/manage_trackers/tracking_detail.dart'; -import 'package:mangayomi/modules/updates/updates_screen.dart'; import 'package:mangayomi/modules/webview/webview.dart'; import 'package:mangayomi/modules/browse/browse_screen.dart'; import 'package:mangayomi/modules/browse/extension/extension_lang.dart'; @@ -117,12 +116,12 @@ class RouterNotifier extends ChangeNotifier { ), ), GoRoute( - name: "feed", - path: '/feed', - builder: (context, state) => const FeedScreen(), + name: "updates", + path: '/updates', + builder: (context, state) => const UpdatesScreen(), pageBuilder: (context, state) => transitionPage( key: state.pageKey, - child: const FeedScreen(), + child: const UpdatesScreen(), ), ), GoRoute( @@ -144,15 +143,6 @@ class RouterNotifier extends ChangeNotifier { ), ), ]), - GoRoute( - name: "updates", - path: '/updates', - builder: (context, state) => const UpdatesScreen(), - pageBuilder: (context, state) => transitionPage( - key: state.pageKey, - child: const UpdatesScreen(), - ), - ), GoRoute( path: "/mangaHome", name: "mangaHome", diff --git a/lib/services/sync_server.dart b/lib/services/sync_server.dart index 7a4c48a..f8ff15f 100644 --- a/lib/services/sync_server.dart +++ b/lib/services/sync_server.dart @@ -4,7 +4,7 @@ import 'package:mangayomi/eval/dart/model/m_bridge.dart'; import 'package:mangayomi/eval/dart/model/source_preference.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/changed_items.dart'; -import 'package:mangayomi/models/feed.dart'; +import 'package:mangayomi/models/update.dart'; import 'package:mangayomi/models/sync_preference.dart'; import 'package:mangayomi/models/track.dart'; import 'package:mangayomi/models/manga.dart'; @@ -206,7 +206,7 @@ class SyncServer extends _$SyncServer { datas["chapters"] = data["chapters"]; datas["tracks"] = data["tracks"]; datas["history"] = data["history"]; - datas["feeds"] = data["feeds"]; + datas["updates"] = data["updates"]; var encodedJson = jsonEncode(datas); return sha256.convert(utf8.encode(encodedJson)).toString(); } @@ -296,13 +296,13 @@ class SyncServer extends _$SyncServer { .map((e) => e.toJson()) .toList(); datas.addAll({"extensions_preferences": sourcePreferences}); - final feeds = isar.feeds + final updates = isar.updates .filter() .idIsNotNull() .findAllSync() .map((e) => e.toJson()) .toList(); - datas.addAll({"feeds": feeds}); + datas.addAll({"updates": updates}); return datas; } @@ -322,8 +322,8 @@ class SyncServer extends _$SyncServer { final history = (backup["history"] as List?) ?.map((e) => History.fromJson(e)) .toList(); - final feeds = - (backup["feeds"] as List?)?.map((e) => Feed.fromJson(e)).toList(); + final updates = + (backup["updates"] as List?)?.map((e) => Update.fromJson(e)).toList(); isar.writeTxnSync(() { isar.mangas.clearSync(); @@ -350,19 +350,19 @@ class SyncServer extends _$SyncServer { } } - isar.feeds.clearSync(); - if (feeds != null) { + isar.updates.clearSync(); + if (updates != null) { final tempChapters = isar.chapters.filter().idIsNotNull().findAllSync().toList(); - for (var feed in feeds) { + for (var update in updates) { final matchingChapter = tempChapters .where((chapter) => - chapter.mangaId == feed.mangaId && - chapter.name == feed.chapterName) + chapter.mangaId == update.mangaId && + chapter.name == update.chapterName) .firstOrNull; if (matchingChapter != null) { - isar.feeds.putSync(feed..chapter.value = matchingChapter); - feed.chapter.saveSync(); + isar.updates.putSync(update..chapter.value = matchingChapter); + update.chapter.saveSync(); } } } @@ -416,8 +416,8 @@ class SyncServer extends _$SyncServer { final extensionsPref = (backup["extensions_preferences"] as List?) ?.map((e) => SourcePreference.fromJson(e)) .toList(); - final feeds = - (backup["feeds"] as List?)?.map((e) => Feed.fromJson(e)).toList(); + final updates = + (backup["updates"] as List?)?.map((e) => Update.fromJson(e)).toList(); isar.writeTxnSync(() { isar.mangas.clearSync(); @@ -444,19 +444,19 @@ class SyncServer extends _$SyncServer { } } - isar.feeds.clearSync(); - if (feeds != null) { + isar.updates.clearSync(); + if (updates != null) { final tempChapters = isar.chapters.filter().idIsNotNull().findAllSync().toList(); - for (var feed in feeds) { + for (var update in updates) { final matchingChapter = tempChapters .where((chapter) => - chapter.mangaId == feed.mangaId && - chapter.name == feed.chapterName) + chapter.mangaId == update.mangaId && + chapter.name == update.chapterName) .firstOrNull; if (matchingChapter != null) { - isar.feeds.putSync(feed..chapter.value = matchingChapter); - feed.chapter.saveSync(); + isar.updates.putSync(update..chapter.value = matchingChapter); + update.chapter.saveSync(); } } } diff --git a/lib/services/sync_server.g.dart b/lib/services/sync_server.g.dart index 87b7a54..b6480d0 100644 --- a/lib/services/sync_server.g.dart +++ b/lib/services/sync_server.g.dart @@ -6,7 +6,7 @@ part of 'sync_server.dart'; // RiverpodGenerator // ************************************************************************** -String _$syncServerHash() => r'e019e8870184d25f7a2659e35f6c3969bc683b50'; +String _$syncServerHash() => r'0f4a07754abea35efb563ba8471b47d1c8854058'; /// Copied from Dart SDK class _SystemHash {