From 661d07716b150b74cb988f4a2297c1a76492e222 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Wed, 14 May 2025 01:38:47 +0800 Subject: [PATCH] :sparkles: Subscriptions --- lib/models/post.dart | 12 ++ lib/models/post.freezed.dart | 139 +++++++++++++++ lib/models/post.g.dart | 16 ++ lib/screens/account/profile.dart | 9 + lib/screens/account/profile.g.dart | 122 +++++++++++++ lib/screens/posts/pub_profile.dart | 109 +++++++++++- lib/screens/posts/pub_profile.g.dart | 254 +++++++++++++++++++++++++++ lib/widgets/post/post_list.dart | 1 - 8 files changed, 653 insertions(+), 9 deletions(-) diff --git a/lib/models/post.dart b/lib/models/post.dart index ae7fae1..cffe712 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -78,6 +78,18 @@ abstract class SnPublisherStats with _$SnPublisherStats { _$SnPublisherStatsFromJson(json); } +@freezed +abstract class SnSubscriptionStatus with _$SnSubscriptionStatus { + const factory SnSubscriptionStatus({ + required bool isSubscribed, + required int publisherId, + required String publisherName, + }) = _SnSubscriptionStatus; + + factory SnSubscriptionStatus.fromJson(Map json) => + _$SnSubscriptionStatusFromJson(json); +} + @freezed abstract class ReactInfo with _$ReactInfo { const factory ReactInfo({required String icon, required int attitude}) = diff --git a/lib/models/post.freezed.dart b/lib/models/post.freezed.dart index 5b59d10..d4e41ff 100644 --- a/lib/models/post.freezed.dart +++ b/lib/models/post.freezed.dart @@ -654,6 +654,145 @@ as int, } +} + + +/// @nodoc +mixin _$SnSubscriptionStatus { + + bool get isSubscribed; int get publisherId; String get publisherName; +/// Create a copy of SnSubscriptionStatus +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SnSubscriptionStatusCopyWith get copyWith => _$SnSubscriptionStatusCopyWithImpl(this as SnSubscriptionStatus, _$identity); + + /// Serializes this SnSubscriptionStatus to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnSubscriptionStatus&&(identical(other.isSubscribed, isSubscribed) || other.isSubscribed == isSubscribed)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisherName, publisherName) || other.publisherName == publisherName)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,isSubscribed,publisherId,publisherName); + +@override +String toString() { + return 'SnSubscriptionStatus(isSubscribed: $isSubscribed, publisherId: $publisherId, publisherName: $publisherName)'; +} + + +} + +/// @nodoc +abstract mixin class $SnSubscriptionStatusCopyWith<$Res> { + factory $SnSubscriptionStatusCopyWith(SnSubscriptionStatus value, $Res Function(SnSubscriptionStatus) _then) = _$SnSubscriptionStatusCopyWithImpl; +@useResult +$Res call({ + bool isSubscribed, int publisherId, String publisherName +}); + + + + +} +/// @nodoc +class _$SnSubscriptionStatusCopyWithImpl<$Res> + implements $SnSubscriptionStatusCopyWith<$Res> { + _$SnSubscriptionStatusCopyWithImpl(this._self, this._then); + + final SnSubscriptionStatus _self; + final $Res Function(SnSubscriptionStatus) _then; + +/// Create a copy of SnSubscriptionStatus +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? isSubscribed = null,Object? publisherId = null,Object? publisherName = null,}) { + return _then(_self.copyWith( +isSubscribed: null == isSubscribed ? _self.isSubscribed : isSubscribed // ignore: cast_nullable_to_non_nullable +as bool,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable +as int,publisherName: null == publisherName ? _self.publisherName : publisherName // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// @nodoc +@JsonSerializable() + +class _SnSubscriptionStatus implements SnSubscriptionStatus { + const _SnSubscriptionStatus({required this.isSubscribed, required this.publisherId, required this.publisherName}); + factory _SnSubscriptionStatus.fromJson(Map json) => _$SnSubscriptionStatusFromJson(json); + +@override final bool isSubscribed; +@override final int publisherId; +@override final String publisherName; + +/// Create a copy of SnSubscriptionStatus +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$SnSubscriptionStatusCopyWith<_SnSubscriptionStatus> get copyWith => __$SnSubscriptionStatusCopyWithImpl<_SnSubscriptionStatus>(this, _$identity); + +@override +Map toJson() { + return _$SnSubscriptionStatusToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnSubscriptionStatus&&(identical(other.isSubscribed, isSubscribed) || other.isSubscribed == isSubscribed)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisherName, publisherName) || other.publisherName == publisherName)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,isSubscribed,publisherId,publisherName); + +@override +String toString() { + return 'SnSubscriptionStatus(isSubscribed: $isSubscribed, publisherId: $publisherId, publisherName: $publisherName)'; +} + + +} + +/// @nodoc +abstract mixin class _$SnSubscriptionStatusCopyWith<$Res> implements $SnSubscriptionStatusCopyWith<$Res> { + factory _$SnSubscriptionStatusCopyWith(_SnSubscriptionStatus value, $Res Function(_SnSubscriptionStatus) _then) = __$SnSubscriptionStatusCopyWithImpl; +@override @useResult +$Res call({ + bool isSubscribed, int publisherId, String publisherName +}); + + + + +} +/// @nodoc +class __$SnSubscriptionStatusCopyWithImpl<$Res> + implements _$SnSubscriptionStatusCopyWith<$Res> { + __$SnSubscriptionStatusCopyWithImpl(this._self, this._then); + + final _SnSubscriptionStatus _self; + final $Res Function(_SnSubscriptionStatus) _then; + +/// Create a copy of SnSubscriptionStatus +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? isSubscribed = null,Object? publisherId = null,Object? publisherName = null,}) { + return _then(_SnSubscriptionStatus( +isSubscribed: null == isSubscribed ? _self.isSubscribed : isSubscribed // ignore: cast_nullable_to_non_nullable +as bool,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable +as int,publisherName: null == publisherName ? _self.publisherName : publisherName // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + } /// @nodoc diff --git a/lib/models/post.g.dart b/lib/models/post.g.dart index 8df7188..71aafa1 100644 --- a/lib/models/post.g.dart +++ b/lib/models/post.g.dart @@ -144,3 +144,19 @@ Map _$SnPublisherStatsToJson(_SnPublisherStats instance) => 'upvote_received': instance.upvoteReceived, 'downvote_received': instance.downvoteReceived, }; + +_SnSubscriptionStatus _$SnSubscriptionStatusFromJson( + Map json, +) => _SnSubscriptionStatus( + isSubscribed: json['is_subscribed'] as bool, + publisherId: (json['publisher_id'] as num).toInt(), + publisherName: json['publisher_name'] as String, +); + +Map _$SnSubscriptionStatusToJson( + _SnSubscriptionStatus instance, +) => { + 'is_subscribed': instance.isSubscribed, + 'publisher_id': instance.publisherId, + 'publisher_name': instance.publisherName, +}; diff --git a/lib/screens/account/profile.dart b/lib/screens/account/profile.dart index ffbc99e..48b6e39 100644 --- a/lib/screens/account/profile.dart +++ b/lib/screens/account/profile.dart @@ -21,6 +21,15 @@ Future account(Ref ref, String uname) async { return SnAccount.fromJson(resp.data); } +@riverpod +Future> accountBadges(Ref ref, String uname) async { + final apiClient = ref.watch(apiClientProvider); + final resp = await apiClient.get("/accounts/$uname/badges"); + return List.from( + resp.data.map((x) => SnAccountBadge.fromJson(x)), + ); +} + @RoutePage() class AccountProfileScreen extends HookConsumerWidget { final String name; diff --git a/lib/screens/account/profile.g.dart b/lib/screens/account/profile.g.dart index 9ba0820..efe824b 100644 --- a/lib/screens/account/profile.g.dart +++ b/lib/screens/account/profile.g.dart @@ -145,5 +145,127 @@ class _AccountProviderElement String get uname => (origin as AccountProvider).uname; } +String _$accountBadgesHash() => r'4bfe5fb0d6ac0d4cde4563460bde289289188f6d'; + +/// See also [accountBadges]. +@ProviderFor(accountBadges) +const accountBadgesProvider = AccountBadgesFamily(); + +/// See also [accountBadges]. +class AccountBadgesFamily extends Family>> { + /// See also [accountBadges]. + const AccountBadgesFamily(); + + /// See also [accountBadges]. + AccountBadgesProvider call(String uname) { + return AccountBadgesProvider(uname); + } + + @override + AccountBadgesProvider getProviderOverride( + covariant AccountBadgesProvider provider, + ) { + return call(provider.uname); + } + + 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'accountBadgesProvider'; +} + +/// See also [accountBadges]. +class AccountBadgesProvider + extends AutoDisposeFutureProvider> { + /// See also [accountBadges]. + AccountBadgesProvider(String uname) + : this._internal( + (ref) => accountBadges(ref as AccountBadgesRef, uname), + from: accountBadgesProvider, + name: r'accountBadgesProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$accountBadgesHash, + dependencies: AccountBadgesFamily._dependencies, + allTransitiveDependencies: + AccountBadgesFamily._allTransitiveDependencies, + uname: uname, + ); + + AccountBadgesProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.uname, + }) : super.internal(); + + final String uname; + + @override + Override overrideWith( + FutureOr> Function(AccountBadgesRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: AccountBadgesProvider._internal( + (ref) => create(ref as AccountBadgesRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + uname: uname, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _AccountBadgesProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is AccountBadgesProvider && other.uname == uname; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, uname.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin AccountBadgesRef on AutoDisposeFutureProviderRef> { + /// The parameter `uname` of this provider. + String get uname; +} + +class _AccountBadgesProviderElement + extends AutoDisposeFutureProviderElement> + with AccountBadgesRef { + _AccountBadgesProviderElement(super.provider); + + @override + String get uname => (origin as AccountBadgesProvider).uname; +} + // 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/posts/pub_profile.dart b/lib/screens/posts/pub_profile.dart index cb42b6d..8786dae 100644 --- a/lib/screens/posts/pub_profile.dart +++ b/lib/screens/posts/pub_profile.dart @@ -1,11 +1,16 @@ import 'package:auto_route/annotations.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/post.dart'; +import 'package:island/models/user.dart'; import 'package:island/pods/network.dart'; +import 'package:island/widgets/account/badge.dart'; import 'package:island/widgets/account/status.dart'; +import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/post/post_list.dart'; @@ -21,6 +26,27 @@ Future publisher(Ref ref, String uname) async { return SnPublisher.fromJson(resp.data); } +@riverpod +Future> publisherBadges(Ref ref, String pubName) async { + final pub = await ref.watch(publisherProvider(pubName).future); + if (pub.publisherType != 0) return []; + final apiClient = ref.watch(apiClientProvider); + final resp = await apiClient.get("/accounts/${pub.name}/badges"); + return List.from( + resp.data.map((x) => SnAccountBadge.fromJson(x)), + ); +} + +@riverpod +Future publisherSubscriptionStatus( + Ref ref, + String pubName, +) async { + final apiClient = ref.watch(apiClientProvider); + final resp = await apiClient.get("/publishers/$pubName/subscription"); + return SnSubscriptionStatus.fromJson(resp.data); +} + @RoutePage() class PublisherProfileScreen extends HookConsumerWidget { final String name; @@ -32,6 +58,38 @@ class PublisherProfileScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final publisher = ref.watch(publisherProvider(name)); + final badges = ref.watch(publisherBadgesProvider(name)); + final subStatus = ref.watch(publisherSubscriptionStatusProvider(name)); + + final subscribing = useState(false); + + Future subscribe() async { + final apiClient = ref.watch(apiClientProvider); + subscribing.value = true; + try { + await apiClient.post("/publishers/$name/subscribe", data: {'tier': 0}); + ref.invalidate(publisherSubscriptionStatusProvider(name)); + HapticFeedback.heavyImpact(); + } catch (err) { + showErrorAlert(err); + } finally { + subscribing.value = false; + } + } + + Future unsubscribe() async { + final apiClient = ref.watch(apiClientProvider); + subscribing.value = true; + try { + await apiClient.post("/publishers/$name/unsubscribe"); + ref.invalidate(publisherSubscriptionStatusProvider(name)); + HapticFeedback.heavyImpact(); + } catch (err) { + showErrorAlert(err); + } finally { + subscribing.value = false; + } + } final iconShadow = Shadow( color: Colors.black54, @@ -64,6 +122,41 @@ class PublisherProfileScreen extends HookConsumerWidget { ), ), ), + actions: [ + subStatus.when( + data: + (status) => IconButton( + onPressed: + subscribing.value + ? null + : (status.isSubscribed + ? unsubscribe + : subscribe), + icon: Icon( + status.isSubscribed + ? Icons.remove_circle + : Icons.add_circle, + shadows: [iconShadow], + ), + ), + error: (_, __) => const SizedBox(), + loading: + () => const SizedBox( + width: 48, + height: 48, + child: Center( + child: SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + ), + ), + ), + ), + ), + const Gap(8), + ], ), SliverToBoxAdapter( child: Row( @@ -95,14 +188,14 @@ class PublisherProfileScreen extends HookConsumerWidget { ], ).padding(horizontal: 24, top: 24, bottom: 24), ), - // if (data.badges.isNotEmpty) - // SliverToBoxAdapter( - // child: BadgeList( - // badges: data.badges, - // ).padding(horizontal: 24, bottom: 24), - // ) - // else - // const Gap(16), + if (badges.value?.isNotEmpty ?? false) + SliverToBoxAdapter( + child: BadgeList( + badges: badges.value!, + ).padding(horizontal: 24, bottom: 24), + ) + else + const SliverGap(16), SliverToBoxAdapter(child: const Divider(height: 1)), if (data.bio.isNotEmpty) SliverToBoxAdapter( diff --git a/lib/screens/posts/pub_profile.g.dart b/lib/screens/posts/pub_profile.g.dart index 26eba9d..595e9a8 100644 --- a/lib/screens/posts/pub_profile.g.dart +++ b/lib/screens/posts/pub_profile.g.dart @@ -145,5 +145,259 @@ class _PublisherProviderElement String get uname => (origin as PublisherProvider).uname; } +String _$publisherBadgesHash() => r'69a5bbc9e1528da65ae8b1e5e6c4f57c3dcf4071'; + +/// See also [publisherBadges]. +@ProviderFor(publisherBadges) +const publisherBadgesProvider = PublisherBadgesFamily(); + +/// See also [publisherBadges]. +class PublisherBadgesFamily extends Family>> { + /// See also [publisherBadges]. + const PublisherBadgesFamily(); + + /// See also [publisherBadges]. + PublisherBadgesProvider call(String pubName) { + return PublisherBadgesProvider(pubName); + } + + @override + PublisherBadgesProvider getProviderOverride( + covariant PublisherBadgesProvider provider, + ) { + return call(provider.pubName); + } + + 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'publisherBadgesProvider'; +} + +/// See also [publisherBadges]. +class PublisherBadgesProvider + extends AutoDisposeFutureProvider> { + /// See also [publisherBadges]. + PublisherBadgesProvider(String pubName) + : this._internal( + (ref) => publisherBadges(ref as PublisherBadgesRef, pubName), + from: publisherBadgesProvider, + name: r'publisherBadgesProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$publisherBadgesHash, + dependencies: PublisherBadgesFamily._dependencies, + allTransitiveDependencies: + PublisherBadgesFamily._allTransitiveDependencies, + pubName: pubName, + ); + + PublisherBadgesProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.pubName, + }) : super.internal(); + + final String pubName; + + @override + Override overrideWith( + FutureOr> Function(PublisherBadgesRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: PublisherBadgesProvider._internal( + (ref) => create(ref as PublisherBadgesRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + pubName: pubName, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _PublisherBadgesProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is PublisherBadgesProvider && other.pubName == pubName; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, pubName.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin PublisherBadgesRef on AutoDisposeFutureProviderRef> { + /// The parameter `pubName` of this provider. + String get pubName; +} + +class _PublisherBadgesProviderElement + extends AutoDisposeFutureProviderElement> + with PublisherBadgesRef { + _PublisherBadgesProviderElement(super.provider); + + @override + String get pubName => (origin as PublisherBadgesProvider).pubName; +} + +String _$publisherSubscriptionStatusHash() => + r'4eb6741c40775c814e71b6a98b8f1e2d84bf7e30'; + +/// See also [publisherSubscriptionStatus]. +@ProviderFor(publisherSubscriptionStatus) +const publisherSubscriptionStatusProvider = PublisherSubscriptionStatusFamily(); + +/// See also [publisherSubscriptionStatus]. +class PublisherSubscriptionStatusFamily + extends Family> { + /// See also [publisherSubscriptionStatus]. + const PublisherSubscriptionStatusFamily(); + + /// See also [publisherSubscriptionStatus]. + PublisherSubscriptionStatusProvider call(String pubName) { + return PublisherSubscriptionStatusProvider(pubName); + } + + @override + PublisherSubscriptionStatusProvider getProviderOverride( + covariant PublisherSubscriptionStatusProvider provider, + ) { + return call(provider.pubName); + } + + 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'publisherSubscriptionStatusProvider'; +} + +/// See also [publisherSubscriptionStatus]. +class PublisherSubscriptionStatusProvider + extends AutoDisposeFutureProvider { + /// See also [publisherSubscriptionStatus]. + PublisherSubscriptionStatusProvider(String pubName) + : this._internal( + (ref) => publisherSubscriptionStatus( + ref as PublisherSubscriptionStatusRef, + pubName, + ), + from: publisherSubscriptionStatusProvider, + name: r'publisherSubscriptionStatusProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$publisherSubscriptionStatusHash, + dependencies: PublisherSubscriptionStatusFamily._dependencies, + allTransitiveDependencies: + PublisherSubscriptionStatusFamily._allTransitiveDependencies, + pubName: pubName, + ); + + PublisherSubscriptionStatusProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.pubName, + }) : super.internal(); + + final String pubName; + + @override + Override overrideWith( + FutureOr Function( + PublisherSubscriptionStatusRef provider, + ) + create, + ) { + return ProviderOverride( + origin: this, + override: PublisherSubscriptionStatusProvider._internal( + (ref) => create(ref as PublisherSubscriptionStatusRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + pubName: pubName, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _PublisherSubscriptionStatusProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is PublisherSubscriptionStatusProvider && + other.pubName == pubName; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, pubName.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin PublisherSubscriptionStatusRef + on AutoDisposeFutureProviderRef { + /// The parameter `pubName` of this provider. + String get pubName; +} + +class _PublisherSubscriptionStatusProviderElement + extends AutoDisposeFutureProviderElement + with PublisherSubscriptionStatusRef { + _PublisherSubscriptionStatusProviderElement(super.provider); + + @override + String get pubName => (origin as PublisherSubscriptionStatusProvider).pubName; +} + // 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/widgets/post/post_list.dart b/lib/widgets/post/post_list.dart index f2b8296..6f66ad9 100644 --- a/lib/widgets/post/post_list.dart +++ b/lib/widgets/post/post_list.dart @@ -4,7 +4,6 @@ import 'package:dio/dio.dart'; import 'package:island/models/post.dart'; import 'package:island/pods/network.dart'; import 'package:island/widgets/post/post_item.dart'; -import 'package:styled_widget/styled_widget.dart'; import 'package:very_good_infinite_list/very_good_infinite_list.dart'; // State class to hold posts and pagination info