diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index ef41926..724f520 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 2 -/// Strings: 268 (134 per locale) +/// Strings: 280 (140 per locale) /// -/// Built on 2024-02-25 at 20:04 UTC +/// Built on 2024-02-25 at 20:58 UTC // coverage:ignore-file // ignore_for_file: type=lint @@ -373,6 +373,12 @@ class _StringsBookmarksBookmarkOptionsEn { String get markedAsUnreadSuccessfully => 'Bookmark marked as unread successfully.'; String get bookmarkNotMarkedAsRead => 'The bookmark couldn\'t be marked as read.'; String get bookmarkNotMarkedAsUnread => 'The bookmark couldn\'t be marked as unread.'; + String get archivingBookmark => 'Archiving bookmark...'; + String get unarchivingBookmark => 'Unarchiving bookmark...'; + String get bookmarkArchivedSuccessfully => 'Bookmark archived successfully.'; + String get bookmarkUnrchivedSuccessfully => 'Bookmark unarchived successfully.'; + String get bookmarkNotArchived => 'The bookmark couldn\'t be archived.'; + String get bookmarkNotUnrchived => 'The bookmark couldn\'t be unarchived.'; } // Path: tags.createTag @@ -689,10 +695,16 @@ class _StringsBookmarksBookmarkOptionsEs implements _StringsBookmarksBookmarkOpt @override String get followingBookmarkDeleted => 'El siguiente marcador será eliminado:'; @override String get markingAsRead => 'Marcando como leído...'; @override String get markingAsUnead => 'Marcando como no leído...'; - @override String get markedAsReadSuccessfully => 'Marcador marcado como leído correctamente..'; + @override String get markedAsReadSuccessfully => 'Marcador marcado como leído correctamente.'; @override String get markedAsUnreadSuccessfully => 'Marcador marcado como no leído correctamente.'; @override String get bookmarkNotMarkedAsRead => 'El marcador no se ha podido marcar como leído.'; @override String get bookmarkNotMarkedAsUnread => 'El marcador no se ha podido marcar como no leído.'; + @override String get archivingBookmark => 'Archivando marcador...'; + @override String get unarchivingBookmark => 'Desarchivando marcador...'; + @override String get bookmarkArchivedSuccessfully => 'Marcador archivado correctamente.'; + @override String get bookmarkUnrchivedSuccessfully => 'Marcador desarchivado correctamente.'; + @override String get bookmarkNotArchived => 'El marcador no pudo ser archivado.'; + @override String get bookmarkNotUnrchived => 'El marcador no pudo ser desarchivado.'; } // Path: tags.createTag @@ -854,6 +866,12 @@ extension on Translations { case 'bookmarks.bookmarkOptions.markedAsUnreadSuccessfully': return 'Bookmark marked as unread successfully.'; case 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead': return 'The bookmark couldn\'t be marked as read.'; case 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread': return 'The bookmark couldn\'t be marked as unread.'; + case 'bookmarks.bookmarkOptions.archivingBookmark': return 'Archiving bookmark...'; + case 'bookmarks.bookmarkOptions.unarchivingBookmark': return 'Unarchiving bookmark...'; + case 'bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully': return 'Bookmark archived successfully.'; + case 'bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully': return 'Bookmark unarchived successfully.'; + case 'bookmarks.bookmarkOptions.bookmarkNotArchived': return 'The bookmark couldn\'t be archived.'; + case 'bookmarks.bookmarkOptions.bookmarkNotUnrchived': return 'The bookmark couldn\'t be unarchived.'; case 'tags.tags': return 'Tags'; case 'tags.created': return ({required Object created}) => 'Created: ${created}'; case 'tags.createTag.createTag': return 'Create tag'; @@ -992,10 +1010,16 @@ extension on _StringsEs { case 'bookmarks.bookmarkOptions.followingBookmarkDeleted': return 'El siguiente marcador será eliminado:'; case 'bookmarks.bookmarkOptions.markingAsRead': return 'Marcando como leído...'; case 'bookmarks.bookmarkOptions.markingAsUnead': return 'Marcando como no leído...'; - case 'bookmarks.bookmarkOptions.markedAsReadSuccessfully': return 'Marcador marcado como leído correctamente..'; + case 'bookmarks.bookmarkOptions.markedAsReadSuccessfully': return 'Marcador marcado como leído correctamente.'; case 'bookmarks.bookmarkOptions.markedAsUnreadSuccessfully': return 'Marcador marcado como no leído correctamente.'; case 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead': return 'El marcador no se ha podido marcar como leído.'; case 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread': return 'El marcador no se ha podido marcar como no leído.'; + case 'bookmarks.bookmarkOptions.archivingBookmark': return 'Archivando marcador...'; + case 'bookmarks.bookmarkOptions.unarchivingBookmark': return 'Desarchivando marcador...'; + case 'bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully': return 'Marcador archivado correctamente.'; + case 'bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully': return 'Marcador desarchivado correctamente.'; + case 'bookmarks.bookmarkOptions.bookmarkNotArchived': return 'El marcador no pudo ser archivado.'; + case 'bookmarks.bookmarkOptions.bookmarkNotUnrchived': return 'El marcador no pudo ser desarchivado.'; case 'tags.tags': return 'Etiquetas'; case 'tags.created': return ({required Object created}) => 'Creado: ${created}'; case 'tags.createTag.createTag': return 'Crear etiqueta'; diff --git a/lib/i18n/strings_en.i18n.json b/lib/i18n/strings_en.i18n.json index 9f9e7aa..48d6288 100644 --- a/lib/i18n/strings_en.i18n.json +++ b/lib/i18n/strings_en.i18n.json @@ -94,7 +94,13 @@ "markedAsReadSuccessfully": "Bookmark marked as read successfully.", "markedAsUnreadSuccessfully": "Bookmark marked as unread successfully.", "bookmarkNotMarkedAsRead": "The bookmark couldn't be marked as read.", - "bookmarkNotMarkedAsUnread": "The bookmark couldn't be marked as unread." + "bookmarkNotMarkedAsUnread": "The bookmark couldn't be marked as unread.", + "archivingBookmark": "Archiving bookmark...", + "unarchivingBookmark": "Unarchiving bookmark...", + "bookmarkArchivedSuccessfully": "Bookmark archived successfully.", + "bookmarkUnrchivedSuccessfully": "Bookmark unarchived successfully.", + "bookmarkNotArchived": "The bookmark couldn't be archived.", + "bookmarkNotUnrchived": "The bookmark couldn't be unarchived." } }, "tags": { diff --git a/lib/i18n/strings_es.i18n.json b/lib/i18n/strings_es.i18n.json index 9c78dd3..508367e 100644 --- a/lib/i18n/strings_es.i18n.json +++ b/lib/i18n/strings_es.i18n.json @@ -91,10 +91,16 @@ "followingBookmarkDeleted": "El siguiente marcador será eliminado:", "markingAsRead": "Marcando como leído...", "markingAsUnead": "Marcando como no leído...", - "markedAsReadSuccessfully": "Marcador marcado como leído correctamente..", + "markedAsReadSuccessfully": "Marcador marcado como leído correctamente.", "markedAsUnreadSuccessfully": "Marcador marcado como no leído correctamente.", "bookmarkNotMarkedAsRead": "El marcador no se ha podido marcar como leído.", - "bookmarkNotMarkedAsUnread": "El marcador no se ha podido marcar como no leído." + "bookmarkNotMarkedAsUnread": "El marcador no se ha podido marcar como no leído.", + "archivingBookmark": "Archivando marcador...", + "unarchivingBookmark": "Desarchivando marcador...", + "bookmarkArchivedSuccessfully": "Marcador archivado correctamente.", + "bookmarkUnrchivedSuccessfully": "Marcador desarchivado correctamente.", + "bookmarkNotArchived": "El marcador no pudo ser archivado.", + "bookmarkNotUnrchived": "El marcador no pudo ser desarchivado." } }, "tags": { diff --git a/lib/screens/bookmarks/model/favicon_loader.model.dart b/lib/screens/bookmarks/model/favicon_loader.model.dart index a70753f..4481255 100644 --- a/lib/screens/bookmarks/model/favicon_loader.model.dart +++ b/lib/screens/bookmarks/model/favicon_loader.model.dart @@ -6,6 +6,6 @@ class FaviconLoaderModel { FaviconLoaderModel({ required this.favicons, - this.loadingFavicons = true, + this.loadingFavicons = false, }); } diff --git a/lib/screens/bookmarks/provider/add_bookmark.provider.g.dart b/lib/screens/bookmarks/provider/add_bookmark.provider.g.dart index 78c92a4..14b70e5 100644 --- a/lib/screens/bookmarks/provider/add_bookmark.provider.g.dart +++ b/lib/screens/bookmarks/provider/add_bookmark.provider.g.dart @@ -175,7 +175,7 @@ final getTagsProvider = ); typedef GetTagsRef = AutoDisposeFutureProviderRef>; -String _$addBookmarkHash() => r'ace81358d08fd833b2aa06edddcb10f00728c30c'; +String _$addBookmarkHash() => r'510fe4dbdc6628a13be9d8c5c2581fd5ac94ca68'; /// See also [AddBookmark]. @ProviderFor(AddBookmark) diff --git a/lib/screens/bookmarks/provider/bookmarks.provider.dart b/lib/screens/bookmarks/provider/bookmarks.provider.dart index 952bb1e..9fcc28d 100644 --- a/lib/screens/bookmarks/provider/bookmarks.provider.dart +++ b/lib/screens/bookmarks/provider/bookmarks.provider.dart @@ -1,13 +1,9 @@ -import 'package:flutter/material.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:linkdy/screens/bookmarks/provider/common_functions.dart'; import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart'; import 'package:linkdy/screens/bookmarks/model/bookmarks.model.dart'; -import 'package:linkdy/models/data/set_bookmark_data.dart'; -import 'package:linkdy/utils/process_modal.dart'; -import 'package:linkdy/utils/snackbar.dart'; -import 'package:linkdy/i18n/strings.g.dart'; import 'package:linkdy/models/data/bookmarks.dart'; import 'package:linkdy/providers/api_client.provider.dart'; import 'package:linkdy/constants/enums.dart'; @@ -83,62 +79,45 @@ class Bookmarks extends _$Bookmarks { ref.notifyListeners(); } + void setBookmarks(List bookmarks) { + state.bookmarks = bookmarks; + ref.notifyListeners(); + } + Future refresh() async { await ref.read(bookmarksRequestProvider(state.limit).future); } void deleteBookmark(Bookmark bookmark) async { - final processModal = ProcessModal(); - processModal.open(t.bookmarks.bookmarkOptions.deletingBookmark); - - final result = await ref.read(apiClientProvider)!.postDeleteBookmark(bookmark.id!); - - processModal.close(); - if (result.successful == true) { + final result = await BookmarkCommonFunctions.deleteBookmark( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result == true) { state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); ref.notifyListeners(); - showSnacbkar(label: t.bookmarks.bookmarkOptions.bookmarkDeleted, color: Colors.green); - } else { - showSnacbkar(label: t.bookmarks.bookmarkOptions.bookmarkNotDeleted, color: Colors.red); } } void markAsReadUnread(Bookmark bookmark) async { - final processModal = ProcessModal(); - processModal.open( - bookmark.unread == true ? t.bookmarks.bookmarkOptions.markingAsRead : t.bookmarks.bookmarkOptions.markingAsUnead, + final result = await BookmarkCommonFunctions.markAsReadUnread( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, ); - - final result = await ref.read(apiClientProvider)!.putUpdateBookmark( - bookmark.id!, - SetBookmarkData( - url: bookmark.url!, - description: bookmark.description ?? '', - isArchived: bookmark.isArchived ?? false, - shared: bookmark.shared ?? false, - unread: bookmark.unread == true ? false : true, - tagNames: bookmark.tagNames?.join(",") ?? '', - title: bookmark.title ?? '', - ), - ); - - processModal.close(); - if (result.successful == true) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.content!.id ? result.content! : b).toList(); + if (result != null) { + state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); + ref.notifyListeners(); + } + } + + void archiveUnarchive(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.markAsReadUnread( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result != null) { + state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); ref.notifyListeners(); - showSnacbkar( - label: bookmark.unread == true - ? t.bookmarks.bookmarkOptions.markedAsReadSuccessfully - : t.bookmarks.bookmarkOptions.markedAsUnreadSuccessfully, - color: Colors.green, - ); - } else { - showSnacbkar( - label: bookmark.unread == true - ? t.bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead - : t.bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread, - color: Colors.red, - ); } } } diff --git a/lib/screens/bookmarks/provider/bookmarks.provider.g.dart b/lib/screens/bookmarks/provider/bookmarks.provider.g.dart index 2e3c422..9ad9e9b 100644 --- a/lib/screens/bookmarks/provider/bookmarks.provider.g.dart +++ b/lib/screens/bookmarks/provider/bookmarks.provider.g.dart @@ -172,7 +172,7 @@ final bookmarksRequestLoadMoreProvider = ); typedef BookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef; -String _$bookmarksHash() => r'63863329236a127fce0f7b75e2461a841c0cae55'; +String _$bookmarksHash() => r'82c31fa1cbab1ba1e5c77486e7dc7ce5a86e20a5'; /// See also [Bookmarks]. @ProviderFor(Bookmarks) diff --git a/lib/screens/bookmarks/provider/common_functions.dart b/lib/screens/bookmarks/provider/common_functions.dart new file mode 100644 index 0000000..1cc9547 --- /dev/null +++ b/lib/screens/bookmarks/provider/common_functions.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; + +import 'package:linkdy/i18n/strings.g.dart'; +import 'package:linkdy/models/data/bookmarks.dart'; +import 'package:linkdy/models/data/set_bookmark_data.dart'; +import 'package:linkdy/services/api_client.dart'; +import 'package:linkdy/utils/process_modal.dart'; +import 'package:linkdy/utils/snackbar.dart'; + +class BookmarkCommonFunctions { + static Future deleteBookmark({ + required Bookmark bookmark, + required ApiClientService apiClient, + }) async { + final processModal = ProcessModal(); + processModal.open(t.bookmarks.bookmarkOptions.deletingBookmark); + + final result = await apiClient.postDeleteBookmark(bookmark.id!); + + processModal.close(); + if (result.successful == true) { + showSnacbkar(label: t.bookmarks.bookmarkOptions.bookmarkDeleted, color: Colors.green); + } else { + showSnacbkar(label: t.bookmarks.bookmarkOptions.bookmarkNotDeleted, color: Colors.red); + } + return result.successful; + } + + static Future markAsReadUnread({ + required Bookmark bookmark, + required ApiClientService apiClient, + }) async { + final processModal = ProcessModal(); + processModal.open( + bookmark.unread == true ? t.bookmarks.bookmarkOptions.markingAsRead : t.bookmarks.bookmarkOptions.markingAsUnead, + ); + + final result = await apiClient.putUpdateBookmark( + bookmark.id!, + SetBookmarkData( + url: bookmark.url!, + description: bookmark.description ?? '', + isArchived: bookmark.isArchived ?? false, + shared: bookmark.shared ?? false, + unread: bookmark.unread == true ? false : true, + tagNames: bookmark.tagNames?.join(",") ?? '', + title: bookmark.title ?? '', + ), + ); + + processModal.close(); + if (result.successful == true) { + showSnacbkar( + label: bookmark.unread == true + ? t.bookmarks.bookmarkOptions.markedAsReadSuccessfully + : t.bookmarks.bookmarkOptions.markedAsUnreadSuccessfully, + color: Colors.green, + ); + return result.content; + } else { + showSnacbkar( + label: bookmark.unread == true + ? t.bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead + : t.bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread, + color: Colors.red, + ); + return null; + } + } + + static Future archiveUnarchive({ + required Bookmark bookmark, + required ApiClientService apiClient, + }) async { + final processModal = ProcessModal(); + processModal.open( + bookmark.unread == true + ? t.bookmarks.bookmarkOptions.archivingBookmark + : t.bookmarks.bookmarkOptions.unarchivingBookmark, + ); + + final result = await apiClient.putUpdateBookmark( + bookmark.id!, + SetBookmarkData( + url: bookmark.url!, + description: bookmark.description ?? '', + unread: bookmark.unread ?? false, + shared: bookmark.shared ?? false, + isArchived: bookmark.isArchived == true ? false : true, + tagNames: bookmark.tagNames?.join(",") ?? '', + title: bookmark.title ?? '', + ), + ); + + processModal.close(); + if (result.successful == true) { + showSnacbkar( + label: bookmark.isArchived == true + ? t.bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully + : t.bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully, + color: Colors.green, + ); + return result.content; + } else { + showSnacbkar( + label: bookmark.isArchived == true + ? t.bookmarks.bookmarkOptions.bookmarkNotUnrchived + : t.bookmarks.bookmarkOptions.bookmarkNotArchived, + color: Colors.red, + ); + return null; + } + } +} diff --git a/lib/screens/bookmarks/provider/favicon_loader.provider.dart b/lib/screens/bookmarks/provider/favicon_loader.provider.dart index 272f58f..f966203 100644 --- a/lib/screens/bookmarks/provider/favicon_loader.provider.dart +++ b/lib/screens/bookmarks/provider/favicon_loader.provider.dart @@ -49,6 +49,8 @@ class FaviconStore extends _$FaviconStore { } void loadFavicons(List bookmarks) async { + if (state.loadingFavicons == true) return; + state.loadingFavicons = true; ref.notifyListeners(); diff --git a/lib/screens/bookmarks/provider/favicon_loader.provider.g.dart b/lib/screens/bookmarks/provider/favicon_loader.provider.g.dart index ef5bbef..f4e401e 100644 --- a/lib/screens/bookmarks/provider/favicon_loader.provider.g.dart +++ b/lib/screens/bookmarks/provider/favicon_loader.provider.g.dart @@ -6,7 +6,7 @@ part of 'favicon_loader.provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$faviconStoreHash() => r'87cd0d0c0df889ca3238b6c05389b8dd351d189c'; +String _$faviconStoreHash() => r'aeda388d2c7d220a43a29825a9850d8d7433d84f'; /// See also [FaviconStore]. @ProviderFor(FaviconStore) diff --git a/lib/screens/bookmarks/provider/search_bookmarks.provider.dart b/lib/screens/bookmarks/provider/search_bookmarks.provider.dart index 09e3f4f..d77e452 100644 --- a/lib/screens/bookmarks/provider/search_bookmarks.provider.dart +++ b/lib/screens/bookmarks/provider/search_bookmarks.provider.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart'; +import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; +import 'package:linkdy/screens/bookmarks/provider/common_functions.dart'; import 'package:linkdy/screens/bookmarks/model/search_bookmarks.model.dart'; import 'package:linkdy/constants/enums.dart'; +import 'package:linkdy/models/data/bookmarks.dart'; import 'package:linkdy/providers/api_client.provider.dart'; part 'search_bookmarks.provider.g.dart'; @@ -19,6 +23,7 @@ FutureOr fetchSearchBookmarks(FetchSearchBookmarksRef ref, int limit) asyn ); if (result.successful == true) { + ref.read(faviconStoreProvider.notifier).loadFavicons(result.content!.results!); ref.read(searchBookmarksProvider).bookmarks = result.content!.results!; ref.read(searchBookmarksProvider).maxNumber = result.content!.count!; ref.read(searchBookmarksProvider).currentPage = 0; @@ -41,9 +46,9 @@ FutureOr fetchSearchBookmarksLoadMore(FetchSearchBookmarksLoadMoreRef ref) limit: provider.limit, offset: newOffset, ); - await Future.delayed(Duration(seconds: 3)); if (result.successful == true) { + ref.read(faviconStoreProvider.notifier).loadFavicons(result.content!.results!); provider.bookmarks = [...provider.bookmarks, ...result.content!.results!]; provider.maxNumber = result.content!.count!; provider.currentPage = provider.currentPage + 1; @@ -92,4 +97,46 @@ class SearchBookmarks extends _$SearchBookmarks { void notifyListeners() { ref.notifyListeners(); } + + void deleteBookmark(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.deleteBookmark( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result == true) { + state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); + ref.notifyListeners(); + ref + .read(bookmarksProvider.notifier) + .setBookmarks(ref.read(bookmarksProvider).bookmarks.where((b) => b.id != bookmark.id).toList()); + } + } + + void markAsReadUnread(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.markAsReadUnread( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result != null) { + state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); + ref.notifyListeners(); + ref + .read(bookmarksProvider.notifier) + .setBookmarks(ref.read(bookmarksProvider).bookmarks.map((b) => b.id == result.id ? result : b).toList()); + } + } + + void archiveUnarchive(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.markAsReadUnread( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result != null) { + state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); + ref.notifyListeners(); + ref + .read(bookmarksProvider.notifier) + .setBookmarks(ref.read(bookmarksProvider).bookmarks.map((b) => b.id == result.id ? result : b).toList()); + } + } } diff --git a/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart b/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart index 1009acc..7715501 100644 --- a/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart +++ b/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart @@ -7,7 +7,7 @@ part of 'search_bookmarks.provider.dart'; // ************************************************************************** String _$fetchSearchBookmarksHash() => - r'dea1740df4ad970bc1ffd90d85aa0d1d2cf94bf2'; + r'a854d28b2c2b6761cfd716bcbe081b54fbbf29ef'; /// Copied from Dart SDK class _SystemHash { @@ -158,7 +158,7 @@ class _FetchSearchBookmarksProviderElement } String _$fetchSearchBookmarksLoadMoreHash() => - r'4c085e4dc487554a209fa73170294b5b8e279c24'; + r'f07a6a89f5a87a0f26d3a8d2d49f1d98ce36a287'; /// See also [fetchSearchBookmarksLoadMore]. @ProviderFor(fetchSearchBookmarksLoadMore) @@ -174,7 +174,7 @@ final fetchSearchBookmarksLoadMoreProvider = ); typedef FetchSearchBookmarksLoadMoreRef = AutoDisposeFutureProviderRef; -String _$searchBookmarksHash() => r'db9f8d8cc488e820791e22c594ad9046da73ec25'; +String _$searchBookmarksHash() => r'843fe597bceab3e3f512b5b4a40ddd1dbeb09f9d'; /// See also [SearchBookmarks]. @ProviderFor(SearchBookmarks) diff --git a/lib/screens/bookmarks/ui/bookmark_item.dart b/lib/screens/bookmarks/ui/bookmark_item.dart index e838a42..0ff6575 100644 --- a/lib/screens/bookmarks/ui/bookmark_item.dart +++ b/lib/screens/bookmarks/ui/bookmark_item.dart @@ -1,11 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart'; import 'package:linkdy/i18n/strings.g.dart'; @@ -18,10 +17,14 @@ import 'package:linkdy/utils/open_url.dart'; class BookmarkItem extends ConsumerWidget { final Bookmark bookmark; + final void Function(Bookmark bookmark) onDelete; + final void Function(Bookmark bookmark) onReadUnread; const BookmarkItem({ Key? key, required this.bookmark, + required this.onDelete, + required this.onReadUnread, }) : super(key: key); @override @@ -36,34 +39,27 @@ class BookmarkItem extends ConsumerWidget { } } - void openDeleteBookmarkModal(BuildContext ctx) { - showDialog( - context: context, - builder: (context) => DeleteBookmarkModal(bookmark: bookmark), - ); - } - return Slidable( startActionPane: ActionPane( motion: const DrawerMotion(), - extentRatio: 0.75, + extentRatio: 0.5, children: [ SlidableAction( - onPressed: (ctx) => ref.read(bookmarksProvider.notifier).markAsReadUnread(bookmark), + onPressed: (_) => onReadUnread(bookmark), backgroundColor: Colors.blue, label: bookmark.unread == true ? t.bookmarks.bookmarkOptions.read : t.bookmarks.bookmarkOptions.unread, icon: bookmark.unread == true ? Icons.mark_email_read_rounded : Icons.mark_as_unread_rounded, padding: const EdgeInsets.all(4), ), + // SlidableAction( + // onPressed: (ctx) => {}, + // backgroundColor: Colors.grey, + // label: t.bookmarks.bookmarkOptions.archive, + // icon: Icons.archive_rounded, + // padding: const EdgeInsets.all(4), + // ), SlidableAction( - onPressed: (ctx) => {}, - backgroundColor: Colors.grey, - label: t.bookmarks.bookmarkOptions.archive, - icon: Icons.archive_rounded, - padding: const EdgeInsets.all(4), - ), - SlidableAction( - onPressed: (ctx) => {}, + onPressed: (ctx) => Share.shareUri(Uri.parse(bookmark.url!)), backgroundColor: Colors.orange, label: t.bookmarks.bookmarkOptions.share, icon: Icons.share_rounded, @@ -83,7 +79,7 @@ class BookmarkItem extends ConsumerWidget { padding: const EdgeInsets.all(4), ), SlidableAction( - onPressed: openDeleteBookmarkModal, + onPressed: (_) => onDelete(bookmark), backgroundColor: Colors.red, label: t.bookmarks.bookmarkOptions.delete, icon: Icons.delete_rounded, @@ -228,13 +224,23 @@ class BookmarkItem extends ConsumerWidget { borderRadius: BorderRadius.circular(10), color: Theme.of(context).colorScheme.primaryContainer, ), - child: Text( - t.bookmarks.bookmarkOptions.unread, - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.onPrimaryContainer, - fontWeight: FontWeight.w700, - ), + child: Row( + children: [ + Icon( + Icons.mark_as_unread_rounded, + size: 12, + color: Theme.of(context).colorScheme.onPrimaryContainer, + ), + const SizedBox(width: 4), + Text( + t.bookmarks.bookmarkOptions.unread, + style: TextStyle( + fontSize: 10, + color: Theme.of(context).colorScheme.onPrimaryContainer, + fontWeight: FontWeight.w700, + ), + ), + ], ), ), ], diff --git a/lib/screens/bookmarks/ui/bookmarks.dart b/lib/screens/bookmarks/ui/bookmarks.dart index 015246e..181fb48 100644 --- a/lib/screens/bookmarks/ui/bookmarks.dart +++ b/lib/screens/bookmarks/ui/bookmarks.dart @@ -7,11 +7,13 @@ import 'package:linkdy/constants/enums.dart'; import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; import 'package:linkdy/screens/bookmarks/ui/bookmark_item.dart'; import 'package:linkdy/screens/bookmarks/ui/add_bookmark_modal.dart'; +import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; import 'package:linkdy/widgets/error_screen.dart'; import 'package:linkdy/widgets/no_data_screen.dart'; import 'package:linkdy/i18n/strings.g.dart'; import 'package:linkdy/providers/router.provider.dart'; +import 'package:linkdy/models/data/bookmarks.dart'; import 'package:linkdy/router/paths.dart'; class BookmarksScreen extends ConsumerWidget { @@ -39,6 +41,8 @@ class BookmarksScreen extends ConsumerWidget { ); } + void openDeleteBookmarkModal(Bookmark bookmark) {} + bool scrollListener(ScrollUpdateNotification scrollNotification) { if (scrollNotification.metrics.extentAfter < 100 && bookmarks.loadingMore == false && @@ -118,7 +122,17 @@ class BookmarksScreen extends ConsumerWidget { // Bottom gap for FAB return const SizedBox(height: 80); } - return BookmarkItem(bookmark: bookmarks.bookmarks[index]); + return BookmarkItem( + bookmark: bookmarks.bookmarks[index], + onReadUnread: ref.read(bookmarksProvider.notifier).markAsReadUnread, + onDelete: (bookmark) => showDialog( + context: context, + builder: (context) => DeleteBookmarkModal( + bookmark: bookmark, + onDelete: ref.read(bookmarksProvider.notifier).deleteBookmark, + ), + ), + ); }, ), ], diff --git a/lib/screens/bookmarks/ui/delete_bookmark_modal.dart b/lib/screens/bookmarks/ui/delete_bookmark_modal.dart index 33d699e..26668d5 100644 --- a/lib/screens/bookmarks/ui/delete_bookmark_modal.dart +++ b/lib/screens/bookmarks/ui/delete_bookmark_modal.dart @@ -1,21 +1,20 @@ import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; import 'package:linkdy/i18n/strings.g.dart'; import 'package:linkdy/models/data/bookmarks.dart'; -class DeleteBookmarkModal extends ConsumerWidget { +class DeleteBookmarkModal extends StatelessWidget { final Bookmark bookmark; + final void Function(Bookmark) onDelete; const DeleteBookmarkModal({ Key? key, required this.bookmark, + required this.onDelete, }) : super(key: key); @override - Widget build(BuildContext context, WidgetRef ref) { + Widget build(BuildContext context) { return AlertDialog( title: Column( children: [ @@ -57,7 +56,7 @@ class DeleteBookmarkModal extends ConsumerWidget { TextButton( onPressed: () { Navigator.pop(context); - ref.read(bookmarksProvider.notifier).deleteBookmark(bookmark); + onDelete(bookmark); }, child: Text(t.generic.confirm), ), diff --git a/lib/screens/bookmarks/ui/search_bookmarks.dart b/lib/screens/bookmarks/ui/search_bookmarks.dart index 2d484d6..3521c84 100644 --- a/lib/screens/bookmarks/ui/search_bookmarks.dart +++ b/lib/screens/bookmarks/ui/search_bookmarks.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:linkdy/screens/bookmarks/provider/search_bookmarks.provider.dart'; import 'package:linkdy/screens/bookmarks/ui/bookmark_item.dart'; +import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; import 'package:linkdy/widgets/enter_search_term_screen.dart'; import 'package:linkdy/widgets/error_screen.dart'; @@ -113,6 +114,14 @@ class SearchBookmarksScreen extends ConsumerWidget { } return BookmarkItem( bookmark: provider.bookmarks[index], + onReadUnread: ref.read(searchBookmarksProvider.notifier).markAsReadUnread, + onDelete: (bookmark) => showDialog( + context: context, + builder: (context) => DeleteBookmarkModal( + bookmark: bookmark, + onDelete: ref.read(searchBookmarksProvider.notifier).deleteBookmark, + ), + ), ); }, ), diff --git a/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.dart b/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.dart index 5b1e701..beaf019 100644 --- a/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.dart +++ b/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.dart @@ -1,7 +1,10 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart'; +import 'package:linkdy/screens/bookmarks/provider/common_functions.dart'; import 'package:linkdy/screens/tag_bookmarks/model/tag_bookmarks.model.dart'; +import 'package:linkdy/models/data/bookmarks.dart'; import 'package:linkdy/constants/enums.dart'; import 'package:linkdy/models/data/tags.dart'; import 'package:linkdy/providers/api_client.provider.dart'; @@ -10,19 +13,20 @@ part 'tag_bookmarks.provider.g.dart'; @riverpod FutureOr tagBookmarksRequest(TagBookmarksRequestRef ref, Tag? tag, String? tagId, int limit) async { - final tagResult = tag == null ? await ref.watch(apiClientProvider)!.fetchTagById(tagId!) : null; + final tagResult = tag == null ? await ref.read(apiClientProvider)!.fetchTagById(tagId!) : null; if (tagResult != null && tagResult.successful == false) { ref.read(tagBookmarksProvider.notifier).setInitialLoadStatus(LoadStatus.error); return; } - final bookmarksResult = await ref.watch(apiClientProvider)!.fetchBookmarks( + final bookmarksResult = await ref.read(apiClientProvider)!.fetchBookmarks( q: tag != null ? tag.name : tagResult!.content!.name, limit: limit, offset: 0, ); if (bookmarksResult.successful == true) { + ref.read(faviconStoreProvider.notifier).loadFavicons(bookmarksResult.content!.results!); ref.read(tagBookmarksProvider).bookmarks = bookmarksResult.content!.results!; ref.read(tagBookmarksProvider).maxNumber = bookmarksResult.content!.count!; if (tag == null) ref.read(tagBookmarksProvider).tag = tagResult!.content!; @@ -38,17 +42,18 @@ FutureOr tagBookmarksRequest(TagBookmarksRequestRef ref, Tag? tag, String? @riverpod FutureOr tagBookmarksRequestLoadMore(TagBookmarksRequestLoadMoreRef ref) async { - final provider = ref.watch(tagBookmarksProvider); + final provider = ref.read(tagBookmarksProvider); final newOffset = provider.limit * (provider.currentPage + 1); - final result = await ref.watch(apiClientProvider)!.fetchBookmarks( + final result = await ref.read(apiClientProvider)!.fetchBookmarks( q: provider.tag!.name, limit: provider.limit, offset: newOffset, ); - await Future.delayed(Duration(seconds: 4)); + if (result.successful == true) { + ref.read(faviconStoreProvider.notifier).loadFavicons(result.content!.results!); provider.bookmarks = [...provider.bookmarks, ...result.content!.results!]; provider.maxNumber = result.content!.count!; provider.currentPage = provider.currentPage + 1; @@ -91,4 +96,37 @@ class TagBookmarks extends _$TagBookmarks { void notifyListeners() { ref.notifyListeners(); } + + void deleteBookmark(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.deleteBookmark( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result == true) { + state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); + ref.notifyListeners(); + } + } + + void markAsReadUnread(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.markAsReadUnread( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result != null) { + state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); + ref.notifyListeners(); + } + } + + void archiveUnarchive(Bookmark bookmark) async { + final result = await BookmarkCommonFunctions.markAsReadUnread( + bookmark: bookmark, + apiClient: ref.read(apiClientProvider)!, + ); + if (result != null) { + state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); + ref.notifyListeners(); + } + } } diff --git a/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.g.dart b/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.g.dart index cbcc869..4e43f8b 100644 --- a/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.g.dart +++ b/lib/screens/tag_bookmarks/provider/tag_bookmarks.provider.g.dart @@ -7,7 +7,7 @@ part of 'tag_bookmarks.provider.dart'; // ************************************************************************** String _$tagBookmarksRequestHash() => - r'92613aa119dadb65b7b399b9c779197673689908'; + r'9a4d4582b680da41069054429315f85976378524'; /// Copied from Dart SDK class _SystemHash { @@ -190,7 +190,7 @@ class _TagBookmarksRequestProviderElement } String _$tagBookmarksRequestLoadMoreHash() => - r'3235c66b13a41c52611b86c2b26ecf9376ca1524'; + r'ce7c52c446c2d4b8593fd06e818b3499bdc36a39'; /// See also [tagBookmarksRequestLoadMore]. @ProviderFor(tagBookmarksRequestLoadMore) @@ -206,7 +206,7 @@ final tagBookmarksRequestLoadMoreProvider = ); typedef TagBookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef; -String _$tagBookmarksHash() => r'74e6463830052de2f05c628455d5ccca9faef765'; +String _$tagBookmarksHash() => r'452c0ac002a2c1a5b841d4233fc177a8281f9ea1'; /// See also [TagBookmarks]. @ProviderFor(TagBookmarks) diff --git a/lib/screens/tag_bookmarks/ui/tag_bookmarks.dart b/lib/screens/tag_bookmarks/ui/tag_bookmarks.dart index b01dce0..cc04053 100644 --- a/lib/screens/tag_bookmarks/ui/tag_bookmarks.dart +++ b/lib/screens/tag_bookmarks/ui/tag_bookmarks.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:linkdy/screens/bookmarks/ui/bookmark_item.dart'; +import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; import 'package:linkdy/screens/tag_bookmarks/provider/tag_bookmarks.provider.dart'; import 'package:linkdy/widgets/error_screen.dart'; import 'package:linkdy/widgets/no_data_screen.dart'; @@ -30,7 +31,7 @@ class TagBookmarksScreenState extends ConsumerState { @override void initState() { if (widget.tag == null && widget.tagId == null) { - final router = ref.watch(routerProvider); + final router = ref.read(routerProvider); while (router.canPop() == true) { router.pop(); } @@ -59,7 +60,7 @@ class TagBookmarksScreenState extends ConsumerState { provider.loadingMore == false && provider.bookmarks.length < provider.maxNumber) { ref.read(tagBookmarksProvider.notifier).setLoadingMore(true); - ref.watch(tagBookmarksRequestLoadMoreProvider); + ref.read(tagBookmarksRequestLoadMoreProvider); } return false; } @@ -128,6 +129,14 @@ class TagBookmarksScreenState extends ConsumerState { } return BookmarkItem( bookmark: provider.bookmarks[index], + onReadUnread: ref.read(tagBookmarksProvider.notifier).markAsReadUnread, + onDelete: (bookmark) => showDialog( + context: context, + builder: (context) => DeleteBookmarkModal( + bookmark: bookmark, + onDelete: ref.read(tagBookmarksProvider.notifier).deleteBookmark, + ), + ), ); }, ),