From 1232318a5d25ab0cb2c2c99eba26697d1d0b4030 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 23 Aug 2025 01:32:58 +0800 Subject: [PATCH] :sparkles: Add feed subscription (wip) --- lib/route.dart | 18 + lib/screens/account.dart | 10 + lib/screens/discovery/feeds/feed_detail.dart | 189 +++++++++++ .../discovery/feeds/feed_detail.g.dart | 313 ++++++++++++++++++ .../discovery/feeds/feed_marketplace.dart | 169 ++++++++++ .../discovery/feeds/feed_marketplace.g.dart | 180 ++++++++++ .../stickers/sticker_marketplace.g.dart | 2 +- 7 files changed, 880 insertions(+), 1 deletion(-) create mode 100644 lib/screens/discovery/feeds/feed_detail.dart create mode 100644 lib/screens/discovery/feeds/feed_detail.g.dart create mode 100644 lib/screens/discovery/feeds/feed_marketplace.dart create mode 100644 lib/screens/discovery/feeds/feed_marketplace.g.dart diff --git a/lib/route.dart b/lib/route.dart index a9e18bb7..9dbe54bd 100644 --- a/lib/route.dart +++ b/lib/route.dart @@ -37,6 +37,8 @@ import 'package:island/screens/creators/stickers/stickers.dart'; import 'package:island/screens/creators/stickers/pack_detail.dart'; import 'package:island/screens/stickers/sticker_marketplace.dart'; import 'package:island/screens/stickers/pack_detail.dart'; +import 'package:island/screens/discovery/feeds/feed_marketplace.dart'; +import 'package:island/screens/discovery/feeds/feed_detail.dart'; import 'package:island/screens/creators/poll/poll_list.dart'; import 'package:island/screens/creators/publishers.dart'; import 'package:island/screens/creators/webfeed/webfeed_list.dart'; @@ -546,6 +548,22 @@ final routerProvider = Provider((ref) { ), ], ), + GoRoute( + name: 'webFeedMarketplace', + path: '/feeds', + builder: + (context, state) => const MarketplaceWebFeedsScreen(), + routes: [ + GoRoute( + name: 'webFeedDetail', + path: ':feedId', + builder: (context, state) { + final feedId = state.pathParameters['feedId']!; + return MarketplaceWebFeedDetailScreen(id: feedId); + }, + ), + ], + ), GoRoute( name: 'notifications', path: '/account/notifications', diff --git a/lib/screens/account.dart b/lib/screens/account.dart index 1d375810..16ad8e78 100644 --- a/lib/screens/account.dart +++ b/lib/screens/account.dart @@ -236,6 +236,16 @@ class AccountScreen extends HookConsumerWidget { context.pushNamed('stickerMarketplace'); }, ), + ListTile( + minTileHeight: 48, + leading: const Icon(Symbols.rss_feed), + trailing: const Icon(Symbols.chevron_right), + contentPadding: EdgeInsets.symmetric(horizontal: 24), + title: Text('webFeeds').tr(), + onTap: () { + context.pushNamed('webFeedMarketplace'); + }, + ), ListTile( minTileHeight: 48, leading: const Icon(Symbols.star), diff --git a/lib/screens/discovery/feeds/feed_detail.dart b/lib/screens/discovery/feeds/feed_detail.dart new file mode 100644 index 00000000..a2740071 --- /dev/null +++ b/lib/screens/discovery/feeds/feed_detail.dart @@ -0,0 +1,189 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:gap/gap.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/models/webfeed.dart'; +import 'package:island/pods/network.dart'; +import 'package:island/widgets/alert.dart'; +import 'package:island/widgets/app_scaffold.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:styled_widget/styled_widget.dart'; + +part 'feed_detail.g.dart'; + +/// Provider for web feed articles content +@riverpod +Future> marketplaceWebFeedContent( + Ref ref, { + required String feedId, +}) async { + final apiClient = ref.watch(apiClientProvider); + final resp = await apiClient.get('/sphere/feeds/$feedId/articles'); + return (resp.data as List).map((e) => SnWebArticle.fromJson(e)).toList(); +} + +/// Provider for web feed subscription status +@riverpod +Future marketplaceWebFeedSubscription( + Ref ref, { + required String feedId, +}) async { + final api = ref.watch(apiClientProvider); + try { + await api.get('/sphere/feeds/$feedId/subscription'); + // If not 404, consider subscribed + return true; + } on Object catch (e) { + // Dio error handling agnostic: treat 404 as not-subscribed, rethrow others + final msg = e.toString(); + if (msg.contains('404')) return false; + rethrow; + } +} + +class MarketplaceWebFeedDetailScreen extends HookConsumerWidget { + final String id; + const MarketplaceWebFeedDetailScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + // TODO: Need to create a web feed provider similar to stickerPackProvider + // For now, we'll fetch the feed directly + final feedContent = ref.watch( + marketplaceWebFeedContentProvider(feedId: id), + ); + final subscribed = ref.watch( + marketplaceWebFeedSubscriptionProvider(feedId: id), + ); + + // Subscribe to web feed + Future subscribeToFeed() async { + final apiClient = ref.watch(apiClientProvider); + await apiClient.post('/sphere/feeds/$id/subscribe'); + HapticFeedback.selectionClick(); + ref.invalidate(marketplaceWebFeedSubscriptionProvider(feedId: id)); + if (!context.mounted) return; + showSnackBar('feedSubscribed'.tr()); + } + + // Unsubscribe from web feed + Future unsubscribeFromFeed() async { + final apiClient = ref.watch(apiClientProvider); + await apiClient.delete('/sphere/feeds/$id/subscribe'); + HapticFeedback.selectionClick(); + ref.invalidate(marketplaceWebFeedSubscriptionProvider(feedId: id)); + if (!context.mounted) return; + showSnackBar('feedUnsubscribed'.tr()); + } + + // TODO: Replace with actual feed data provider once created + final dummyFeed = SnWebFeed( + id: id, + url: 'https://example.com', + title: 'Loading...', + publisherId: 'publisher-id', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ); + + return AppScaffold( + appBar: AppBar(title: Text(dummyFeed.title)), + body: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Feed meta + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text(dummyFeed.description ?? ''), + Row( + spacing: 4, + children: [ + const Icon(Symbols.rss_feed, size: 16), + Text('${feedContent.value?.length ?? 0} articles'), + ], + ).opacity(0.85), + Row( + spacing: 4, + children: [ + const Icon(Symbols.link, size: 16), + SelectableText(dummyFeed.url), + ], + ).opacity(0.85), + ], + ).padding(horizontal: 24, vertical: 24), + const Divider(height: 1), + // Articles list + Expanded( + child: feedContent.when( + data: + (articles) => RefreshIndicator( + onRefresh: + () => ref.refresh( + marketplaceWebFeedContentProvider(feedId: id).future, + ), + child: ListView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 20, + ), + itemCount: articles.length, + itemBuilder: (context, index) { + final article = articles[index]; + return Card( + child: ListTile( + title: Text(article.title), + subtitle: Text(article.author ?? ''), + trailing: const Icon(Symbols.open_in_new), + onTap: () { + // TODO: Navigate to article detail or open URL + }, + ), + ); + }, + ), + ), + error: + (err, _) => + Text( + 'Error: $err', + ).textAlignment(TextAlign.center).center(), + loading: () => const CircularProgressIndicator().center(), + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8), + child: subscribed.when( + data: + (isSubscribed) => FilledButton.icon( + onPressed: + isSubscribed ? unsubscribeFromFeed : subscribeToFeed, + icon: Icon( + isSubscribed ? Symbols.remove_circle : Symbols.add_circle, + ), + label: Text( + isSubscribed ? 'unsubscribe'.tr() : 'subscribe'.tr(), + ), + ), + loading: + () => const SizedBox( + height: 32, + width: 32, + child: CircularProgressIndicator(strokeWidth: 2), + ), + error: + (_, _) => OutlinedButton.icon( + onPressed: subscribeToFeed, + icon: const Icon(Symbols.add_circle), + label: Text('subscribe').tr(), + ), + ), + ), + Gap(MediaQuery.of(context).padding.bottom), + ], + ), + ); + } +} diff --git a/lib/screens/discovery/feeds/feed_detail.g.dart b/lib/screens/discovery/feeds/feed_detail.g.dart new file mode 100644 index 00000000..80dd05f0 --- /dev/null +++ b/lib/screens/discovery/feeds/feed_detail.g.dart @@ -0,0 +1,313 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'feed_detail.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$marketplaceWebFeedContentHash() => + r'4e65350bff4055302e15ec14266cdebb1cd89bbe'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// Provider for web feed articles content +/// +/// Copied from [marketplaceWebFeedContent]. +@ProviderFor(marketplaceWebFeedContent) +const marketplaceWebFeedContentProvider = MarketplaceWebFeedContentFamily(); + +/// Provider for web feed articles content +/// +/// Copied from [marketplaceWebFeedContent]. +class MarketplaceWebFeedContentFamily + extends Family>> { + /// Provider for web feed articles content + /// + /// Copied from [marketplaceWebFeedContent]. + const MarketplaceWebFeedContentFamily(); + + /// Provider for web feed articles content + /// + /// Copied from [marketplaceWebFeedContent]. + MarketplaceWebFeedContentProvider call({required String feedId}) { + return MarketplaceWebFeedContentProvider(feedId: feedId); + } + + @override + MarketplaceWebFeedContentProvider getProviderOverride( + covariant MarketplaceWebFeedContentProvider provider, + ) { + return call(feedId: provider.feedId); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'marketplaceWebFeedContentProvider'; +} + +/// Provider for web feed articles content +/// +/// Copied from [marketplaceWebFeedContent]. +class MarketplaceWebFeedContentProvider + extends AutoDisposeFutureProvider> { + /// Provider for web feed articles content + /// + /// Copied from [marketplaceWebFeedContent]. + MarketplaceWebFeedContentProvider({required String feedId}) + : this._internal( + (ref) => marketplaceWebFeedContent( + ref as MarketplaceWebFeedContentRef, + feedId: feedId, + ), + from: marketplaceWebFeedContentProvider, + name: r'marketplaceWebFeedContentProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$marketplaceWebFeedContentHash, + dependencies: MarketplaceWebFeedContentFamily._dependencies, + allTransitiveDependencies: + MarketplaceWebFeedContentFamily._allTransitiveDependencies, + feedId: feedId, + ); + + MarketplaceWebFeedContentProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.feedId, + }) : super.internal(); + + final String feedId; + + @override + Override overrideWith( + FutureOr> Function(MarketplaceWebFeedContentRef provider) + create, + ) { + return ProviderOverride( + origin: this, + override: MarketplaceWebFeedContentProvider._internal( + (ref) => create(ref as MarketplaceWebFeedContentRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + feedId: feedId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _MarketplaceWebFeedContentProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is MarketplaceWebFeedContentProvider && other.feedId == feedId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, feedId.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin MarketplaceWebFeedContentRef + on AutoDisposeFutureProviderRef> { + /// The parameter `feedId` of this provider. + String get feedId; +} + +class _MarketplaceWebFeedContentProviderElement + extends AutoDisposeFutureProviderElement> + with MarketplaceWebFeedContentRef { + _MarketplaceWebFeedContentProviderElement(super.provider); + + @override + String get feedId => (origin as MarketplaceWebFeedContentProvider).feedId; +} + +String _$marketplaceWebFeedSubscriptionHash() => + r'2ff06a48ed7d4236b57412ecca55e94c0a0b6330'; + +/// Provider for web feed subscription status +/// +/// Copied from [marketplaceWebFeedSubscription]. +@ProviderFor(marketplaceWebFeedSubscription) +const marketplaceWebFeedSubscriptionProvider = + MarketplaceWebFeedSubscriptionFamily(); + +/// Provider for web feed subscription status +/// +/// Copied from [marketplaceWebFeedSubscription]. +class MarketplaceWebFeedSubscriptionFamily extends Family> { + /// Provider for web feed subscription status + /// + /// Copied from [marketplaceWebFeedSubscription]. + const MarketplaceWebFeedSubscriptionFamily(); + + /// Provider for web feed subscription status + /// + /// Copied from [marketplaceWebFeedSubscription]. + MarketplaceWebFeedSubscriptionProvider call({required String feedId}) { + return MarketplaceWebFeedSubscriptionProvider(feedId: feedId); + } + + @override + MarketplaceWebFeedSubscriptionProvider getProviderOverride( + covariant MarketplaceWebFeedSubscriptionProvider provider, + ) { + return call(feedId: provider.feedId); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'marketplaceWebFeedSubscriptionProvider'; +} + +/// Provider for web feed subscription status +/// +/// Copied from [marketplaceWebFeedSubscription]. +class MarketplaceWebFeedSubscriptionProvider + extends AutoDisposeFutureProvider { + /// Provider for web feed subscription status + /// + /// Copied from [marketplaceWebFeedSubscription]. + MarketplaceWebFeedSubscriptionProvider({required String feedId}) + : this._internal( + (ref) => marketplaceWebFeedSubscription( + ref as MarketplaceWebFeedSubscriptionRef, + feedId: feedId, + ), + from: marketplaceWebFeedSubscriptionProvider, + name: r'marketplaceWebFeedSubscriptionProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$marketplaceWebFeedSubscriptionHash, + dependencies: MarketplaceWebFeedSubscriptionFamily._dependencies, + allTransitiveDependencies: + MarketplaceWebFeedSubscriptionFamily._allTransitiveDependencies, + feedId: feedId, + ); + + MarketplaceWebFeedSubscriptionProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.feedId, + }) : super.internal(); + + final String feedId; + + @override + Override overrideWith( + FutureOr Function(MarketplaceWebFeedSubscriptionRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: MarketplaceWebFeedSubscriptionProvider._internal( + (ref) => create(ref as MarketplaceWebFeedSubscriptionRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + feedId: feedId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _MarketplaceWebFeedSubscriptionProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is MarketplaceWebFeedSubscriptionProvider && + other.feedId == feedId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, feedId.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin MarketplaceWebFeedSubscriptionRef on AutoDisposeFutureProviderRef { + /// The parameter `feedId` of this provider. + String get feedId; +} + +class _MarketplaceWebFeedSubscriptionProviderElement + extends AutoDisposeFutureProviderElement + with MarketplaceWebFeedSubscriptionRef { + _MarketplaceWebFeedSubscriptionProviderElement(super.provider); + + @override + String get feedId => + (origin as MarketplaceWebFeedSubscriptionProvider).feedId; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/screens/discovery/feeds/feed_marketplace.dart b/lib/screens/discovery/feeds/feed_marketplace.dart new file mode 100644 index 00000000..28767a68 --- /dev/null +++ b/lib/screens/discovery/feeds/feed_marketplace.dart @@ -0,0 +1,169 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:go_router/go_router.dart'; +import 'package:gap/gap.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/models/webfeed.dart'; +import 'package:island/pods/network.dart'; +import 'package:island/widgets/app_scaffold.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'dart:async'; + +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; + +part 'feed_marketplace.g.dart'; + +@riverpod +class MarketplaceWebFeedsNotifier extends _$MarketplaceWebFeedsNotifier + with CursorPagingNotifierMixin { + String? _query; + + @override + Future> build({required String? query}) { + _query = query; + return fetch(cursor: null); + } + + @override + Future> fetch({required String? cursor}) async { + final client = ref.read(apiClientProvider); + final offset = cursor == null ? 0 : int.parse(cursor); + + final response = await client.get( + '/sphere/feeds', + queryParameters: { + 'offset': offset, + 'take': 20, + if (_query != null && _query!.isNotEmpty) 'query': _query, + }, + ); + + final total = int.parse(response.headers.value('X-Total') ?? '0'); + final List data = response.data; + final feeds = data.map((e) => SnWebFeed.fromJson(e)).toList(); + + final hasMore = offset + feeds.length < total; + final nextCursor = hasMore ? (offset + feeds.length).toString() : null; + + return CursorPagingData( + items: feeds, + hasMore: hasMore, + nextCursor: nextCursor, + ); + } +} + +/// Marketplace screen for browsing web feeds. +class MarketplaceWebFeedsScreen extends HookConsumerWidget { + const MarketplaceWebFeedsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final query = useState(null); + final searchController = useTextEditingController(); + final focusNode = useFocusNode(); + final debounceTimer = useState(null); + + // Clear search when query is cleared + useEffect(() { + if (query.value == null || query.value!.isEmpty) { + searchController.clear(); + } + return null; + }, [query.value]); + + // Clean up timer on dispose + useEffect(() { + return () { + debounceTimer.value?.cancel(); + }; + }, []); + + return AppScaffold( + appBar: AppBar( + title: const Text('webFeeds').tr(), + actions: const [Gap(8)], + ), + body: PagingHelperView( + provider: marketplaceWebFeedsNotifierProvider(query: query.value), + futureRefreshable: + marketplaceWebFeedsNotifierProvider(query: query.value).future, + notifierRefreshable: + marketplaceWebFeedsNotifierProvider(query: query.value).notifier, + contentBuilder: + (data, widgetCount, endItemView) => Column( + children: [ + // Search bar above the list + Padding( + padding: const EdgeInsets.all(16), + child: SearchBar( + elevation: WidgetStateProperty.all(4), + controller: searchController, + focusNode: focusNode, + hintText: 'search'.tr(), + leading: const Icon(Symbols.search), + padding: WidgetStateProperty.all( + const EdgeInsets.symmetric(horizontal: 24), + ), + onTapOutside: + (_) => FocusManager.instance.primaryFocus?.unfocus(), + trailing: [ + if (query.value != null && query.value!.isNotEmpty) + IconButton( + icon: const Icon(Symbols.close), + onPressed: () { + query.value = null; + searchController.clear(); + focusNode.unfocus(); + }, + ), + ], + onChanged: (value) { + // Debounce search to avoid excessive API calls + debounceTimer.value?.cancel(); + debounceTimer.value = Timer( + const Duration(milliseconds: 500), + () { + query.value = value.isEmpty ? null : value; + }, + ); + }, + onSubmitted: (value) { + query.value = value.isEmpty ? null : value; + focusNode.unfocus(); + }, + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: widgetCount, + itemBuilder: (context, index) { + if (index == widgetCount - 1) { + return endItemView; + } + + final feed = data.items[index]; + return ListTile( + title: Text(feed.title), + subtitle: Text(feed.description ?? ''), + trailing: const Icon(Symbols.chevron_right), + onTap: () { + // Navigate to web feed detail page + context.pushNamed( + 'webFeedDetail', + pathParameters: {'feedId': feed.id}, + ); + }, + ); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/discovery/feeds/feed_marketplace.g.dart b/lib/screens/discovery/feeds/feed_marketplace.g.dart new file mode 100644 index 00000000..6e31f8cf --- /dev/null +++ b/lib/screens/discovery/feeds/feed_marketplace.g.dart @@ -0,0 +1,180 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'feed_marketplace.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$marketplaceWebFeedsNotifierHash() => + r'dbf885d95570ca9c2259a58998975db813b18cbb'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +abstract class _$MarketplaceWebFeedsNotifier + extends BuildlessAutoDisposeAsyncNotifier> { + late final String? query; + + FutureOr> build({required String? query}); +} + +/// See also [MarketplaceWebFeedsNotifier]. +@ProviderFor(MarketplaceWebFeedsNotifier) +const marketplaceWebFeedsNotifierProvider = MarketplaceWebFeedsNotifierFamily(); + +/// See also [MarketplaceWebFeedsNotifier]. +class MarketplaceWebFeedsNotifierFamily + extends Family>> { + /// See also [MarketplaceWebFeedsNotifier]. + const MarketplaceWebFeedsNotifierFamily(); + + /// See also [MarketplaceWebFeedsNotifier]. + MarketplaceWebFeedsNotifierProvider call({required String? query}) { + return MarketplaceWebFeedsNotifierProvider(query: query); + } + + @override + MarketplaceWebFeedsNotifierProvider getProviderOverride( + covariant MarketplaceWebFeedsNotifierProvider provider, + ) { + return call(query: provider.query); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'marketplaceWebFeedsNotifierProvider'; +} + +/// See also [MarketplaceWebFeedsNotifier]. +class MarketplaceWebFeedsNotifierProvider + extends + AutoDisposeAsyncNotifierProviderImpl< + MarketplaceWebFeedsNotifier, + CursorPagingData + > { + /// See also [MarketplaceWebFeedsNotifier]. + MarketplaceWebFeedsNotifierProvider({required String? query}) + : this._internal( + () => MarketplaceWebFeedsNotifier()..query = query, + from: marketplaceWebFeedsNotifierProvider, + name: r'marketplaceWebFeedsNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$marketplaceWebFeedsNotifierHash, + dependencies: MarketplaceWebFeedsNotifierFamily._dependencies, + allTransitiveDependencies: + MarketplaceWebFeedsNotifierFamily._allTransitiveDependencies, + query: query, + ); + + MarketplaceWebFeedsNotifierProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.query, + }) : super.internal(); + + final String? query; + + @override + FutureOr> runNotifierBuild( + covariant MarketplaceWebFeedsNotifier notifier, + ) { + return notifier.build(query: query); + } + + @override + Override overrideWith(MarketplaceWebFeedsNotifier Function() create) { + return ProviderOverride( + origin: this, + override: MarketplaceWebFeedsNotifierProvider._internal( + () => create()..query = query, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + query: query, + ), + ); + } + + @override + AutoDisposeAsyncNotifierProviderElement< + MarketplaceWebFeedsNotifier, + CursorPagingData + > + createElement() { + return _MarketplaceWebFeedsNotifierProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is MarketplaceWebFeedsNotifierProvider && other.query == query; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, query.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin MarketplaceWebFeedsNotifierRef + on AutoDisposeAsyncNotifierProviderRef> { + /// The parameter `query` of this provider. + String? get query; +} + +class _MarketplaceWebFeedsNotifierProviderElement + extends + AutoDisposeAsyncNotifierProviderElement< + MarketplaceWebFeedsNotifier, + CursorPagingData + > + with MarketplaceWebFeedsNotifierRef { + _MarketplaceWebFeedsNotifierProviderElement(super.provider); + + @override + String? get query => (origin as MarketplaceWebFeedsNotifierProvider).query; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/screens/stickers/sticker_marketplace.g.dart b/lib/screens/stickers/sticker_marketplace.g.dart index a569ae23..9065c875 100644 --- a/lib/screens/stickers/sticker_marketplace.g.dart +++ b/lib/screens/stickers/sticker_marketplace.g.dart @@ -7,7 +7,7 @@ part of 'sticker_marketplace.dart'; // ************************************************************************** String _$marketplaceStickerPacksNotifierHash() => - r'711eafeadf488485521563d0831676c51772d13c'; + r'3bde76e18bb024f45ff6261fe735cdba97b02808'; /// Copied from Dart SDK class _SystemHash {