From 411c71dae0882105b366c929ce314f8cd2271d03 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 27 Dec 2025 23:19:58 +0800 Subject: [PATCH] :lipstick: Improve performance and bugs --- lib/pods/chat/messages_notifier.g.dart | 2 +- lib/screens/notification.dart | 4 +- lib/screens/posts/publisher_profile.g.dart | 2 +- lib/screens/tabs.dart | 3 +- lib/widgets/post/post_shared.dart | 97 +++++++++++++-------- lib/widgets/post/post_shared.g.dart | 98 ++++++++++++++++++++++ 6 files changed, 166 insertions(+), 40 deletions(-) diff --git a/lib/pods/chat/messages_notifier.g.dart b/lib/pods/chat/messages_notifier.g.dart index 6ba0d760..65d08897 100644 --- a/lib/pods/chat/messages_notifier.g.dart +++ b/lib/pods/chat/messages_notifier.g.dart @@ -50,7 +50,7 @@ final class MessagesNotifierProvider } } -String _$messagesNotifierHash() => r'2f3f19cb99357184e82d66e74a31863fcfc48856'; +String _$messagesNotifierHash() => r'284625cff963ff26375d50d7202a33184e810fcb'; final class MessagesNotifierFamily extends $Family with diff --git a/lib/screens/notification.dart b/lib/screens/notification.dart index 77cee084..ddfb09df 100644 --- a/lib/screens/notification.dart +++ b/lib/screens/notification.dart @@ -185,7 +185,9 @@ class NotificationListNotifier extends AsyncNotifier> .toList(); final unreadCount = notifications.where((n) => n.viewedAt == null).length; - ref.read(notificationUnreadCountProvider.notifier).decrement(unreadCount); + if (ref.mounted) { + ref.read(notificationUnreadCountProvider.notifier).decrement(unreadCount); + } return notifications; } diff --git a/lib/screens/posts/publisher_profile.g.dart b/lib/screens/posts/publisher_profile.g.dart index 786e20f9..1b3ab72d 100644 --- a/lib/screens/posts/publisher_profile.g.dart +++ b/lib/screens/posts/publisher_profile.g.dart @@ -221,7 +221,7 @@ final class PublisherSubscriptionStatusProvider } String _$publisherSubscriptionStatusHash() => - r'accf6a0cdf98f8b0474d94ac575e8b20448adc79'; + r'688bf38554afea9e68b2cb59c5f08c6e8dd31b62'; final class PublisherSubscriptionStatusFamily extends $Family with $FunctionalFamilyOverride, String> { diff --git a/lib/screens/tabs.dart b/lib/screens/tabs.dart index c2fcc9fe..665d5aca 100644 --- a/lib/screens/tabs.dart +++ b/lib/screens/tabs.dart @@ -13,6 +13,7 @@ import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/navigation/conditional_bottom_nav.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:island/pods/chat/chat_summary.dart'; +import 'package:styled_widget/styled_widget.dart'; final currentRouteProvider = NotifierProvider( CurrentRouteNotifier.new, @@ -237,7 +238,7 @@ class TabsScreen extends HookConsumerWidget { indicatorColor: Theme.of( context, ).colorScheme.primary.withOpacity(0.2), - ), + ).padding(horizontal: 12), ), ), ), diff --git a/lib/widgets/post/post_shared.dart b/lib/widgets/post/post_shared.dart index 4bf14732..28cb133b 100644 --- a/lib/widgets/post/post_shared.dart +++ b/lib/widgets/post/post_shared.dart @@ -24,6 +24,46 @@ part 'post_shared.g.dart'; const kMessageEnableEmbedTypes = ['text', 'messages.new']; +class RepliesState { + final List posts; + final bool loading; + + RepliesState({required this.posts, required this.loading}); + + RepliesState copyWith({List? posts, bool? loading}) { + return RepliesState( + posts: posts ?? this.posts, + loading: loading ?? this.loading, + ); + } +} + +@riverpod +class RepliesNotifier extends _$RepliesNotifier { + @override + RepliesState build(String parentId) { + return RepliesState(posts: [], loading: false); + } + + Future fetchMore(int pageSize) async { + state = state.copyWith(loading: true); + + final client = ref.read(apiClientProvider); + + final response = await client.get( + '/sphere/posts/$parentId/replies', + queryParameters: {'offset': state.posts.length, 'take': pageSize}, + ); + + if (!ref.mounted) return; + + state = state.copyWith( + posts: [...state.posts, ...response.data.map((e) => SnPost.fromJson(e))], + loading: false, + ); + } +} + @riverpod Future postFeaturedReply(Ref ref, String id) async { final client = ref.watch(apiClientProvider); @@ -82,39 +122,18 @@ class PostReplyPreview extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final posts = useState>([]); - final loading = useState(false); - - Future fetchMoreReplies({int pageSize = 3}) async { - final client = ref.read(apiClientProvider); - loading.value = true; - - try { - final response = await client.get( - '/sphere/posts/${parent.id}/replies', - queryParameters: {'offset': posts.value.length, 'take': pageSize}, - ); - try { - posts.value = [ - ...posts.value, - ...response.data.map((e) => SnPost.fromJson(e)), - ]; - } catch (_) { - // ignore disposed - } - } catch (err) { - showErrorAlert(err); - } finally { - try { - loading.value = false; - } catch (_) { - // ignore disposed - } - } - } + final repliesState = ref.watch(repliesProvider(parent.id)); useEffect(() { - if (isAutoload) fetchMoreReplies(); + if (isAutoload) { + Future(() async { + try { + await ref.read(repliesProvider(parent.id).notifier).fetchMore(3); + } catch (err) { + showErrorAlert(err); + } + }); + } return null; }, [parent]); @@ -127,7 +146,7 @@ class PostReplyPreview extends HookConsumerWidget { ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - for (final post in posts.value) + for (final post in repliesState.posts) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -183,7 +202,7 @@ class PostReplyPreview extends HookConsumerWidget { ).padding(left: 24), ], ), - if (loading.value) + if (repliesState.loading) Row( mainAxisSize: MainAxisSize.min, spacing: 8, @@ -196,7 +215,7 @@ class PostReplyPreview extends HookConsumerWidget { Text('loading').tr(), ], ) - else if (posts.value.length < parent.repliesCount) + else if (repliesState.posts.length < parent.repliesCount) GestureDetector( child: Row( mainAxisSize: MainAxisSize.min, @@ -206,8 +225,14 @@ class PostReplyPreview extends HookConsumerWidget { Text('repliesLoadMore').tr(), ], ), - onTap: () { - fetchMoreReplies(); + onTap: () async { + try { + await ref + .read(repliesProvider(parent.id).notifier) + .fetchMore(3); + } catch (err) { + showErrorAlert(err); + } }, ), ], diff --git a/lib/widgets/post/post_shared.g.dart b/lib/widgets/post/post_shared.g.dart index 927b8038..bcf0effe 100644 --- a/lib/widgets/post/post_shared.g.dart +++ b/lib/widgets/post/post_shared.g.dart @@ -9,6 +9,104 @@ part of 'post_shared.dart'; // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: type=lint, type=warning +@ProviderFor(RepliesNotifier) +const repliesProvider = RepliesNotifierFamily._(); + +final class RepliesNotifierProvider + extends $NotifierProvider { + const RepliesNotifierProvider._({ + required RepliesNotifierFamily super.from, + required String super.argument, + }) : super( + retry: null, + name: r'repliesProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$repliesNotifierHash(); + + @override + String toString() { + return r'repliesProvider' + '' + '($argument)'; + } + + @$internal + @override + RepliesNotifier create() => RepliesNotifier(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(RepliesState value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } + + @override + bool operator ==(Object other) { + return other is RepliesNotifierProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$repliesNotifierHash() => r'2fa51bc3b8cc640e68fa316f61d00f8a0a3740ed'; + +final class RepliesNotifierFamily extends $Family + with + $ClassFamilyOverride< + RepliesNotifier, + RepliesState, + RepliesState, + RepliesState, + String + > { + const RepliesNotifierFamily._() + : super( + retry: null, + name: r'repliesProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + RepliesNotifierProvider call(String parentId) => + RepliesNotifierProvider._(argument: parentId, from: this); + + @override + String toString() => r'repliesProvider'; +} + +abstract class _$RepliesNotifier extends $Notifier { + late final _$args = ref.$arg as String; + String get parentId => _$args; + + RepliesState build(String parentId); + @$mustCallSuper + @override + void runBuild() { + final created = build(_$args); + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + RepliesState, + Object?, + Object? + >; + element.handleValue(ref, created); + } +} + @ProviderFor(postFeaturedReply) const postFeaturedReplyProvider = PostFeaturedReplyFamily._();