Added shared bookmarks screen and archived bookmarks screen
This commit is contained in:
@@ -145,7 +145,7 @@ class BookmarkCommonFunctions {
|
||||
if (result.successful == true) {
|
||||
showSnackbar(
|
||||
key: scaffoldMessengerKey,
|
||||
label: bookmark.isArchived == true
|
||||
label: bookmark.shared == true
|
||||
? t.bookmarks.shareOptions.bookmarkUnsharedSuccessfully
|
||||
: t.bookmarks.shareOptions.bookmarkSharedSuccessfully,
|
||||
color: Colors.green,
|
||||
@@ -154,7 +154,7 @@ class BookmarkCommonFunctions {
|
||||
} else {
|
||||
showSnackbar(
|
||||
key: scaffoldMessengerKey,
|
||||
label: bookmark.isArchived == true
|
||||
label: bookmark.shared == true
|
||||
? t.bookmarks.shareOptions.bookmarkNotUnshared
|
||||
: t.bookmarks.shareOptions.bookmarkNotShared,
|
||||
color: Colors.red,
|
||||
|
||||
@@ -63,8 +63,10 @@ class BookmarkItem extends ConsumerWidget {
|
||||
SlidableAction(
|
||||
onPressed: (ctx) => onArchiveUnarchive(bookmark),
|
||||
backgroundColor: Colors.grey,
|
||||
label: t.bookmarks.bookmarkOptions.archive,
|
||||
icon: Icons.archive_rounded,
|
||||
label: bookmark.isArchived == true
|
||||
? t.bookmarks.bookmarkOptions.unarchive
|
||||
: t.bookmarks.bookmarkOptions.archive,
|
||||
icon: bookmark.isArchived == true ? Icons.unarchive_rounded : Icons.archive_rounded,
|
||||
padding: const EdgeInsets.all(4),
|
||||
),
|
||||
SlidableAction(
|
||||
@@ -73,7 +75,7 @@ class BookmarkItem extends ConsumerWidget {
|
||||
builder: (ctx) => ShareOptionsModal(bookmark: bookmark, onShareInternally: onShareInternally),
|
||||
),
|
||||
backgroundColor: Colors.orange,
|
||||
label: t.bookmarks.bookmarkOptions.share,
|
||||
label: t.bookmarks.bookmarkOptions.shareOptions,
|
||||
icon: Icons.share_rounded,
|
||||
padding: const EdgeInsets.all(4),
|
||||
),
|
||||
|
||||
@@ -12,6 +12,8 @@ import 'package:linkdy/widgets/error_screen.dart';
|
||||
import 'package:linkdy/widgets/no_data_screen.dart';
|
||||
|
||||
import 'package:linkdy/constants/enums.dart';
|
||||
import 'package:linkdy/providers/router.provider.dart';
|
||||
import 'package:linkdy/router/paths.dart';
|
||||
import 'package:linkdy/constants/global_keys.dart';
|
||||
import 'package:linkdy/i18n/strings.g.dart';
|
||||
|
||||
@@ -68,6 +70,30 @@ class BookmarksScreen extends ConsumerWidget {
|
||||
icon: const Icon(Icons.search_rounded),
|
||||
tooltip: t.bookmarks.search.searchBookmarks,
|
||||
),
|
||||
PopupMenuButton(
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
onTap: () => ref.read(routerProvider).push(RoutesPaths.archivedBookmarks),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.archive_rounded),
|
||||
const SizedBox(width: 16),
|
||||
Text(t.bookmarks.archived),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () => ref.read(routerProvider).push(RoutesPaths.sharedBookmarks),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.share_rounded),
|
||||
const SizedBox(width: 16),
|
||||
Text(t.bookmarks.shared),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -3,7 +3,8 @@ import 'package:linkdy/constants/enums.dart';
|
||||
import 'package:linkdy/models/data/bookmarks.dart';
|
||||
import 'package:linkdy/models/data/tags.dart';
|
||||
|
||||
class TagBookmarksModel {
|
||||
class FilteredBookmarksModel {
|
||||
FilteredBookmarksMode filteredBookmarksMode;
|
||||
String? tagId;
|
||||
Tag? tag;
|
||||
int currentPage;
|
||||
@@ -13,7 +14,8 @@ class TagBookmarksModel {
|
||||
int maxNumber;
|
||||
bool loadingMore;
|
||||
|
||||
TagBookmarksModel({
|
||||
FilteredBookmarksModel({
|
||||
this.filteredBookmarksMode = FilteredBookmarksMode.shared,
|
||||
this.tagId,
|
||||
this.tag,
|
||||
this.currentPage = 0,
|
||||
@@ -0,0 +1,220 @@
|
||||
import 'package:linkdy/constants/global_keys.dart';
|
||||
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/filtered_bookmarks/model/filtered_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';
|
||||
|
||||
part 'filtered_bookmarks.provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
FutureOr<void> tagBookmarksRequest(TagBookmarksRequestRef ref, Tag? tag, String? tagId, int limit) async {
|
||||
final tagResult = tag == null ? await ref.read(apiClientProvider)!.fetchTagById(tagId!) : null;
|
||||
if (tagResult != null && tagResult.successful == false) {
|
||||
ref.read(filteredBookmarksProvider.notifier).setInitialLoadStatus(LoadStatus.error);
|
||||
return;
|
||||
}
|
||||
|
||||
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(filteredBookmarksProvider).bookmarks = bookmarksResult.content!.results!;
|
||||
ref.read(filteredBookmarksProvider).maxNumber = bookmarksResult.content!.count!;
|
||||
if (tag == null) ref.read(filteredBookmarksProvider).tag = tagResult!.content!;
|
||||
ref.read(filteredBookmarksProvider).currentPage = 0;
|
||||
ref.read(filteredBookmarksProvider).loadingMore = false;
|
||||
ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.loaded;
|
||||
} else {
|
||||
ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.error;
|
||||
}
|
||||
|
||||
ref.read(filteredBookmarksProvider.notifier).notifyListeners();
|
||||
}
|
||||
|
||||
@riverpod
|
||||
FutureOr<void> tagBookmarksRequestLoadMore(FilteredBookmarksRequestLoadMoreRef ref) async {
|
||||
final provider = ref.read(filteredBookmarksProvider);
|
||||
|
||||
final newOffset = provider.limit * (provider.currentPage + 1);
|
||||
|
||||
final result = await ref.read(apiClientProvider)!.fetchBookmarks(
|
||||
q: provider.tag!.name,
|
||||
limit: provider.limit,
|
||||
offset: newOffset,
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ref.read(filteredBookmarksProvider.notifier).setLoadingMore(false);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
FutureOr<void> filteredBookmarksRequest(FilteredBookmarksRequestRef ref, FilteredBookmarksMode mode, int limit) async {
|
||||
final bookmarksResult = mode == FilteredBookmarksMode.shared
|
||||
? await ref.read(apiClientProvider)!.fetchSharedBookmarks(
|
||||
limit: limit,
|
||||
offset: 0,
|
||||
)
|
||||
: await ref.read(apiClientProvider)!.fetchArchivedBookmarks(
|
||||
limit: limit,
|
||||
offset: 0,
|
||||
);
|
||||
|
||||
if (bookmarksResult.successful == true) {
|
||||
ref.read(faviconStoreProvider.notifier).loadFavicons(bookmarksResult.content!.results!);
|
||||
ref.read(filteredBookmarksProvider).bookmarks = bookmarksResult.content!.results!;
|
||||
ref.read(filteredBookmarksProvider).maxNumber = bookmarksResult.content!.count!;
|
||||
ref.read(filteredBookmarksProvider).currentPage = 0;
|
||||
ref.read(filteredBookmarksProvider).loadingMore = false;
|
||||
ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.loaded;
|
||||
} else {
|
||||
ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.error;
|
||||
}
|
||||
|
||||
ref.read(filteredBookmarksProvider.notifier).notifyListeners();
|
||||
}
|
||||
|
||||
@riverpod
|
||||
FutureOr<void> filteredBookmarksRequestLoadMore(TagBookmarksRequestLoadMoreRef ref) async {
|
||||
final provider = ref.read(filteredBookmarksProvider);
|
||||
|
||||
final newOffset = provider.limit * (provider.currentPage + 1);
|
||||
|
||||
final result = ref.read(filteredBookmarksProvider).filteredBookmarksMode == FilteredBookmarksMode.shared
|
||||
? await ref.read(apiClientProvider)!.fetchSharedBookmarks(
|
||||
q: provider.tag!.name,
|
||||
limit: provider.limit,
|
||||
offset: newOffset,
|
||||
)
|
||||
: await ref.read(apiClientProvider)!.fetchArchivedBookmarks(
|
||||
q: provider.tag!.name,
|
||||
limit: provider.limit,
|
||||
offset: newOffset,
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ref.read(filteredBookmarksProvider.notifier).setLoadingMore(false);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class FilteredBookmarks extends _$FilteredBookmarks {
|
||||
@override
|
||||
FilteredBookmarksModel build() {
|
||||
return FilteredBookmarksModel(
|
||||
bookmarks: [],
|
||||
);
|
||||
}
|
||||
|
||||
void setMode(FilteredBookmarksMode mode) {
|
||||
state.filteredBookmarksMode = mode;
|
||||
}
|
||||
|
||||
void setCurrentPage(int page) {
|
||||
state.currentPage = page;
|
||||
}
|
||||
|
||||
void setLimit(int limit) {
|
||||
state.limit = limit;
|
||||
}
|
||||
|
||||
void setInitialLoadStatus(LoadStatus status) {
|
||||
state.initialLoadStatus = status;
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
void setLoadingMore(bool status) {
|
||||
state.loadingMore = status;
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
if (state.filteredBookmarksMode == FilteredBookmarksMode.tag) {
|
||||
await ref.read(
|
||||
tagBookmarksRequestProvider(state.tag, state.tagId, state.limit).future,
|
||||
);
|
||||
} else {
|
||||
await ref.read(
|
||||
filteredBookmarksRequestProvider(state.filteredBookmarksMode, state.limit).future,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void notifyListeners() {
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
void deleteBookmark(Bookmark bookmark) async {
|
||||
final result = await BookmarkCommonFunctions.deleteBookmark<FilteredBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks,
|
||||
ref: ref,
|
||||
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<FilteredBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks,
|
||||
ref: ref,
|
||||
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.archiveUnarchive<FilteredBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks,
|
||||
ref: ref,
|
||||
bookmark: bookmark,
|
||||
apiClient: ref.read(apiClientProvider)!,
|
||||
);
|
||||
if (result == true) {
|
||||
state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList();
|
||||
}
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
void shareUnshare(Bookmark bookmark) async {
|
||||
final result = await BookmarkCommonFunctions.shareUnshare<FilteredBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks,
|
||||
ref: ref,
|
||||
bookmark: bookmark,
|
||||
apiClient: ref.read(apiClientProvider)!,
|
||||
);
|
||||
if (result != null && state.filteredBookmarksMode == FilteredBookmarksMode.shared) {
|
||||
state.bookmarks = state.bookmarks.where((b) => b.id != result.id).toList();
|
||||
} else if (result != null && state.filteredBookmarksMode != FilteredBookmarksMode.shared) {
|
||||
state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList();
|
||||
}
|
||||
ref.notifyListeners();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'tag_bookmarks.provider.dart';
|
||||
part of 'filtered_bookmarks.provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$tagBookmarksRequestHash() =>
|
||||
r'9a4d4582b680da41069054429315f85976378524';
|
||||
r'abcde0e4ef3aecf21708a24573ddd4279211e288';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
@@ -190,7 +190,7 @@ class _TagBookmarksRequestProviderElement
|
||||
}
|
||||
|
||||
String _$tagBookmarksRequestLoadMoreHash() =>
|
||||
r'ce7c52c446c2d4b8593fd06e818b3499bdc36a39';
|
||||
r'36205474b3c1d3f18f31af56cc97c700f328a4bc';
|
||||
|
||||
/// See also [tagBookmarksRequestLoadMore].
|
||||
@ProviderFor(tagBookmarksRequestLoadMore)
|
||||
@@ -206,20 +206,187 @@ final tagBookmarksRequestLoadMoreProvider =
|
||||
);
|
||||
|
||||
typedef TagBookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef<void>;
|
||||
String _$tagBookmarksHash() => r'35a9ed7751c2d7e9644907f969fb03950b7b9a04';
|
||||
String _$filteredBookmarksRequestHash() =>
|
||||
r'f5352c5076d8bf2ed0cf738bdc0c0cffc9d18a25';
|
||||
|
||||
/// See also [TagBookmarks].
|
||||
@ProviderFor(TagBookmarks)
|
||||
final tagBookmarksProvider =
|
||||
AutoDisposeNotifierProvider<TagBookmarks, TagBookmarksModel>.internal(
|
||||
TagBookmarks.new,
|
||||
name: r'tagBookmarksProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$tagBookmarksHash,
|
||||
/// See also [filteredBookmarksRequest].
|
||||
@ProviderFor(filteredBookmarksRequest)
|
||||
const filteredBookmarksRequestProvider = FilteredBookmarksRequestFamily();
|
||||
|
||||
/// See also [filteredBookmarksRequest].
|
||||
class FilteredBookmarksRequestFamily extends Family<AsyncValue<void>> {
|
||||
/// See also [filteredBookmarksRequest].
|
||||
const FilteredBookmarksRequestFamily();
|
||||
|
||||
/// See also [filteredBookmarksRequest].
|
||||
FilteredBookmarksRequestProvider call(
|
||||
FilteredBookmarksMode mode,
|
||||
int limit,
|
||||
) {
|
||||
return FilteredBookmarksRequestProvider(
|
||||
mode,
|
||||
limit,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
FilteredBookmarksRequestProvider getProviderOverride(
|
||||
covariant FilteredBookmarksRequestProvider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.mode,
|
||||
provider.limit,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'filteredBookmarksRequestProvider';
|
||||
}
|
||||
|
||||
/// See also [filteredBookmarksRequest].
|
||||
class FilteredBookmarksRequestProvider extends AutoDisposeFutureProvider<void> {
|
||||
/// See also [filteredBookmarksRequest].
|
||||
FilteredBookmarksRequestProvider(
|
||||
FilteredBookmarksMode mode,
|
||||
int limit,
|
||||
) : this._internal(
|
||||
(ref) => filteredBookmarksRequest(
|
||||
ref as FilteredBookmarksRequestRef,
|
||||
mode,
|
||||
limit,
|
||||
),
|
||||
from: filteredBookmarksRequestProvider,
|
||||
name: r'filteredBookmarksRequestProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$filteredBookmarksRequestHash,
|
||||
dependencies: FilteredBookmarksRequestFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
FilteredBookmarksRequestFamily._allTransitiveDependencies,
|
||||
mode: mode,
|
||||
limit: limit,
|
||||
);
|
||||
|
||||
FilteredBookmarksRequestProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.mode,
|
||||
required this.limit,
|
||||
}) : super.internal();
|
||||
|
||||
final FilteredBookmarksMode mode;
|
||||
final int limit;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<void> Function(FilteredBookmarksRequestRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: FilteredBookmarksRequestProvider._internal(
|
||||
(ref) => create(ref as FilteredBookmarksRequestRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
mode: mode,
|
||||
limit: limit,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<void> createElement() {
|
||||
return _FilteredBookmarksRequestProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is FilteredBookmarksRequestProvider &&
|
||||
other.mode == mode &&
|
||||
other.limit == limit;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, mode.hashCode);
|
||||
hash = _SystemHash.combine(hash, limit.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
mixin FilteredBookmarksRequestRef on AutoDisposeFutureProviderRef<void> {
|
||||
/// The parameter `mode` of this provider.
|
||||
FilteredBookmarksMode get mode;
|
||||
|
||||
/// The parameter `limit` of this provider.
|
||||
int get limit;
|
||||
}
|
||||
|
||||
class _FilteredBookmarksRequestProviderElement
|
||||
extends AutoDisposeFutureProviderElement<void>
|
||||
with FilteredBookmarksRequestRef {
|
||||
_FilteredBookmarksRequestProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
FilteredBookmarksMode get mode =>
|
||||
(origin as FilteredBookmarksRequestProvider).mode;
|
||||
@override
|
||||
int get limit => (origin as FilteredBookmarksRequestProvider).limit;
|
||||
}
|
||||
|
||||
String _$filteredBookmarksRequestLoadMoreHash() =>
|
||||
r'a40280a01fcfa3892c76287a5e67e5ab9cc00cd5';
|
||||
|
||||
/// See also [filteredBookmarksRequestLoadMore].
|
||||
@ProviderFor(filteredBookmarksRequestLoadMore)
|
||||
final filteredBookmarksRequestLoadMoreProvider =
|
||||
AutoDisposeFutureProvider<void>.internal(
|
||||
filteredBookmarksRequestLoadMore,
|
||||
name: r'filteredBookmarksRequestLoadMoreProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$filteredBookmarksRequestLoadMoreHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$TagBookmarks = AutoDisposeNotifier<TagBookmarksModel>;
|
||||
typedef FilteredBookmarksRequestLoadMoreRef
|
||||
= AutoDisposeFutureProviderRef<void>;
|
||||
String _$filteredBookmarksHash() => r'acb051c3b3e53c084c8c33d6ec1e80a1aa2a10f7';
|
||||
|
||||
/// See also [FilteredBookmarks].
|
||||
@ProviderFor(FilteredBookmarks)
|
||||
final filteredBookmarksProvider = AutoDisposeNotifierProvider<FilteredBookmarks,
|
||||
FilteredBookmarksModel>.internal(
|
||||
FilteredBookmarks.new,
|
||||
name: r'filteredBookmarksProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$filteredBookmarksHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$FilteredBookmarks = AutoDisposeNotifier<FilteredBookmarksModel>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||
@@ -5,7 +5,7 @@ import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.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/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart';
|
||||
import 'package:linkdy/widgets/error_screen.dart';
|
||||
import 'package:linkdy/widgets/no_data_screen.dart';
|
||||
|
||||
@@ -16,47 +16,58 @@ import 'package:linkdy/providers/router.provider.dart';
|
||||
import 'package:linkdy/router/paths.dart';
|
||||
import 'package:linkdy/i18n/strings.g.dart';
|
||||
|
||||
class TagBookmarksScreen extends ConsumerStatefulWidget {
|
||||
class FilteredBookmarksScreen extends ConsumerStatefulWidget {
|
||||
final FilteredBookmarksMode filteredBookmarksMode;
|
||||
final String? tagId;
|
||||
final Tag? tag;
|
||||
|
||||
const TagBookmarksScreen({
|
||||
const FilteredBookmarksScreen({
|
||||
super.key,
|
||||
required this.tagId,
|
||||
required this.filteredBookmarksMode,
|
||||
this.tagId,
|
||||
this.tag,
|
||||
});
|
||||
|
||||
@override
|
||||
TagBookmarksScreenState createState() => TagBookmarksScreenState();
|
||||
FilteredBookmarksScreenState createState() => FilteredBookmarksScreenState();
|
||||
}
|
||||
|
||||
class TagBookmarksScreenState extends ConsumerState<TagBookmarksScreen> {
|
||||
class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
if (widget.tag == null && widget.tagId == null) {
|
||||
final router = ref.read(routerProvider);
|
||||
while (router.canPop() == true) {
|
||||
router.pop();
|
||||
ref.read(filteredBookmarksProvider.notifier).setMode(widget.filteredBookmarksMode);
|
||||
if (widget.filteredBookmarksMode == FilteredBookmarksMode.tag) {
|
||||
if (widget.tag == null && widget.tagId == null) {
|
||||
final router = ref.read(routerProvider);
|
||||
while (router.canPop() == true) {
|
||||
router.pop();
|
||||
}
|
||||
router.pushReplacement(RoutesPaths.bookmarks);
|
||||
return;
|
||||
}
|
||||
router.pushReplacement(RoutesPaths.bookmarks);
|
||||
return;
|
||||
if (widget.tag != null) {
|
||||
ref.read(filteredBookmarksProvider).tag = widget.tag;
|
||||
}
|
||||
if (widget.tagId != null) {
|
||||
ref.read(filteredBookmarksProvider).tagId = widget.tagId;
|
||||
}
|
||||
ref.read(tagBookmarksRequestProvider(widget.tag, widget.tagId, ref.read(filteredBookmarksProvider).limit));
|
||||
} else {
|
||||
ref.read(
|
||||
filteredBookmarksRequestProvider(widget.filteredBookmarksMode, ref.read(filteredBookmarksProvider).limit),
|
||||
);
|
||||
}
|
||||
if (widget.tag != null) {
|
||||
ref.read(tagBookmarksProvider).tag = widget.tag;
|
||||
}
|
||||
if (widget.tagId != null) {
|
||||
ref.read(tagBookmarksProvider).tagId = widget.tagId;
|
||||
}
|
||||
ref.read(tagBookmarksRequestProvider(widget.tag, widget.tagId, ref.read(tagBookmarksProvider).limit));
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.tag == null && widget.tagId == null) return const Material();
|
||||
if (widget.filteredBookmarksMode == FilteredBookmarksMode.tag && widget.tag == null && widget.tagId == null) {
|
||||
return const Material();
|
||||
}
|
||||
|
||||
final provider = ref.watch(tagBookmarksProvider);
|
||||
final provider = ref.watch(filteredBookmarksProvider);
|
||||
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
@@ -64,14 +75,50 @@ class TagBookmarksScreenState extends ConsumerState<TagBookmarksScreen> {
|
||||
if (scrollNotification.metrics.extentAfter < 100 &&
|
||||
provider.loadingMore == false &&
|
||||
provider.bookmarks.length < provider.maxNumber) {
|
||||
ref.read(tagBookmarksProvider.notifier).setLoadingMore(true);
|
||||
ref.read(filteredBookmarksProvider.notifier).setLoadingMore(true);
|
||||
ref.read(tagBookmarksRequestLoadMoreProvider);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String title() {
|
||||
switch (widget.filteredBookmarksMode) {
|
||||
case FilteredBookmarksMode.tag:
|
||||
return widget.tag != null
|
||||
? "#${widget.tag!.name}"
|
||||
: provider.tag != null
|
||||
? "#${provider.tag!.name}"
|
||||
: '';
|
||||
|
||||
case FilteredBookmarksMode.archived:
|
||||
return t.bookmarks.archived;
|
||||
|
||||
case FilteredBookmarksMode.shared:
|
||||
return t.bookmarks.shared;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
String noContent() {
|
||||
switch (widget.filteredBookmarksMode) {
|
||||
case FilteredBookmarksMode.tag:
|
||||
return t.tags.filteredBookmarks.noBookmarksWithThisTag;
|
||||
|
||||
case FilteredBookmarksMode.archived:
|
||||
return t.tags.filteredBookmarks.noArchivedBookmarks;
|
||||
|
||||
case FilteredBookmarksMode.shared:
|
||||
return t.tags.filteredBookmarks.noSharedBookmarks;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
return ScaffoldMessenger(
|
||||
key: ScaffoldMessengerKeys.tagBookmarks,
|
||||
key: ScaffoldMessengerKeys.filteredBookmarks,
|
||||
child: Scaffold(
|
||||
body: NestedScrollView(
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||
@@ -82,13 +129,7 @@ class TagBookmarksScreenState extends ConsumerState<TagBookmarksScreen> {
|
||||
floating: true,
|
||||
centerTitle: false,
|
||||
forceElevated: innerBoxIsScrolled,
|
||||
title: Text(
|
||||
widget.tag != null
|
||||
? "#${widget.tag!.name}"
|
||||
: provider.tag != null
|
||||
? "#${provider.tag!.name}"
|
||||
: '',
|
||||
),
|
||||
title: Text(title()),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -97,7 +138,7 @@ class TagBookmarksScreenState extends ConsumerState<TagBookmarksScreen> {
|
||||
child: Builder(
|
||||
builder: (context) => RefreshIndicator(
|
||||
displacement: 120,
|
||||
onRefresh: () => ref.read(tagBookmarksProvider.notifier).refresh(),
|
||||
onRefresh: () => ref.read(filteredBookmarksProvider.notifier).refresh(),
|
||||
child: NotificationListener(
|
||||
onNotification: scrollListener,
|
||||
child: CustomScrollView(
|
||||
@@ -118,7 +159,7 @@ class TagBookmarksScreenState extends ConsumerState<TagBookmarksScreen> {
|
||||
if (provider.bookmarks.isEmpty)
|
||||
SliverFillRemaining(
|
||||
child: NoDataScreen(
|
||||
message: t.tags.tagBookmarks.noBookmarksWithThisTag,
|
||||
message: noContent(),
|
||||
),
|
||||
),
|
||||
if (provider.bookmarks.isNotEmpty)
|
||||
@@ -138,16 +179,16 @@ class TagBookmarksScreenState extends ConsumerState<TagBookmarksScreen> {
|
||||
}
|
||||
return BookmarkItem(
|
||||
bookmark: provider.bookmarks[index],
|
||||
onReadUnread: ref.read(tagBookmarksProvider.notifier).markAsReadUnread,
|
||||
onReadUnread: ref.read(filteredBookmarksProvider.notifier).markAsReadUnread,
|
||||
onDelete: (bookmark) => showDialog(
|
||||
context: context,
|
||||
builder: (context) => DeleteBookmarkModal(
|
||||
bookmark: bookmark,
|
||||
onDelete: ref.read(tagBookmarksProvider.notifier).deleteBookmark,
|
||||
onDelete: ref.read(filteredBookmarksProvider.notifier).deleteBookmark,
|
||||
),
|
||||
),
|
||||
onArchiveUnarchive: ref.read(tagBookmarksProvider.notifier).archiveUnarchive,
|
||||
onShareInternally: ref.read(tagBookmarksProvider.notifier).shareUnshare,
|
||||
onArchiveUnarchive: ref.read(filteredBookmarksProvider.notifier).archiveUnarchive,
|
||||
onShareInternally: ref.read(filteredBookmarksProvider.notifier).shareUnshare,
|
||||
onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b),
|
||||
);
|
||||
},
|
||||
@@ -1,153 +0,0 @@
|
||||
import 'package:linkdy/constants/global_keys.dart';
|
||||
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';
|
||||
|
||||
part 'tag_bookmarks.provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
FutureOr<void> tagBookmarksRequest(TagBookmarksRequestRef ref, Tag? tag, String? tagId, int limit) async {
|
||||
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.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!;
|
||||
ref.read(tagBookmarksProvider).currentPage = 0;
|
||||
ref.read(tagBookmarksProvider).loadingMore = false;
|
||||
ref.read(tagBookmarksProvider).initialLoadStatus = LoadStatus.loaded;
|
||||
} else {
|
||||
ref.read(tagBookmarksProvider).initialLoadStatus = LoadStatus.error;
|
||||
}
|
||||
|
||||
ref.read(tagBookmarksProvider.notifier).notifyListeners();
|
||||
}
|
||||
|
||||
@riverpod
|
||||
FutureOr<void> tagBookmarksRequestLoadMore(TagBookmarksRequestLoadMoreRef ref) async {
|
||||
final provider = ref.read(tagBookmarksProvider);
|
||||
|
||||
final newOffset = provider.limit * (provider.currentPage + 1);
|
||||
|
||||
final result = await ref.read(apiClientProvider)!.fetchBookmarks(
|
||||
q: provider.tag!.name,
|
||||
limit: provider.limit,
|
||||
offset: newOffset,
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ref.read(tagBookmarksProvider.notifier).setLoadingMore(false);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class TagBookmarks extends _$TagBookmarks {
|
||||
@override
|
||||
TagBookmarksModel build() {
|
||||
return TagBookmarksModel(
|
||||
bookmarks: [],
|
||||
);
|
||||
}
|
||||
|
||||
void setCurrentPage(int page) {
|
||||
state.currentPage = page;
|
||||
}
|
||||
|
||||
void setLimit(int limit) {
|
||||
state.limit = limit;
|
||||
}
|
||||
|
||||
void setInitialLoadStatus(LoadStatus status) {
|
||||
state.initialLoadStatus = status;
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
void setLoadingMore(bool status) {
|
||||
state.loadingMore = status;
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
await ref.read(tagBookmarksRequestProvider(state.tag, state.tagId, state.limit).future);
|
||||
}
|
||||
|
||||
void notifyListeners() {
|
||||
ref.notifyListeners();
|
||||
}
|
||||
|
||||
void deleteBookmark(Bookmark bookmark) async {
|
||||
final result = await BookmarkCommonFunctions.deleteBookmark<TagBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.tagBookmarks,
|
||||
ref: ref,
|
||||
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<TagBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.tagBookmarks,
|
||||
ref: ref,
|
||||
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.archiveUnarchive<TagBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.tagBookmarks,
|
||||
ref: ref,
|
||||
bookmark: bookmark,
|
||||
apiClient: ref.read(apiClientProvider)!,
|
||||
);
|
||||
if (result == true) {
|
||||
// On this case the bookmark always will pass from unarchived to archived
|
||||
state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList();
|
||||
ref.notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void shareUnshare(Bookmark bookmark) async {
|
||||
final result = await BookmarkCommonFunctions.shareUnshare<TagBookmarksModel>(
|
||||
scaffoldMessengerKey: ScaffoldMessengerKeys.tagBookmarks,
|
||||
ref: ref,
|
||||
bookmark: bookmark,
|
||||
apiClient: ref.read(apiClientProvider)!,
|
||||
);
|
||||
if (result != null) {
|
||||
state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList();
|
||||
ref.notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user