♻️ Migrated to riverpod v3
This commit is contained in:
@@ -22,8 +22,8 @@ class CallScreen extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final ongoingCall = ref.watch(ongoingCallProvider(room.id));
|
||||
final callState = ref.watch(callNotifierProvider);
|
||||
final callNotifier = ref.watch(callNotifierProvider.notifier);
|
||||
final callState = ref.watch(callProvider);
|
||||
final callNotifier = ref.watch(callProvider.notifier);
|
||||
|
||||
useEffect(() {
|
||||
talker.info('[Call] Joining the call...');
|
||||
|
||||
@@ -191,7 +191,7 @@ class ChatListBodyWidget extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final chats = ref.watch(chatRoomJoinedNotifierProvider);
|
||||
final chats = ref.watch(chatRoomJoinedProvider);
|
||||
|
||||
Widget bodyWidget = Column(
|
||||
children: [
|
||||
@@ -214,7 +214,7 @@ class ChatListBodyWidget extends HookConsumerWidget {
|
||||
(items) => RefreshIndicator(
|
||||
onRefresh:
|
||||
() => Future.sync(() {
|
||||
ref.invalidate(chatRoomJoinedNotifierProvider);
|
||||
ref.invalidate(chatRoomJoinedProvider);
|
||||
}),
|
||||
child: SuperListView.builder(
|
||||
padding: EdgeInsets.only(bottom: 96),
|
||||
@@ -264,7 +264,7 @@ class ChatListBodyWidget extends HookConsumerWidget {
|
||||
(error, stack) => ResponseErrorWidget(
|
||||
error: error,
|
||||
onRetry: () {
|
||||
ref.invalidate(chatRoomJoinedNotifierProvider);
|
||||
ref.invalidate(chatRoomJoinedProvider);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -341,7 +341,7 @@ class ChatListScreen extends HookConsumerWidget {
|
||||
|
||||
// Listen for chat rooms refresh events
|
||||
final subscription = eventBus.on<ChatRoomsRefreshEvent>().listen((event) {
|
||||
ref.invalidate(chatRoomJoinedNotifierProvider);
|
||||
ref.invalidate(chatRoomJoinedProvider);
|
||||
});
|
||||
|
||||
return () {
|
||||
@@ -353,13 +353,14 @@ class ChatListScreen extends HookConsumerWidget {
|
||||
// Set FAB type to chat
|
||||
final fabMenuNotifier = ref.read(fabMenuTypeProvider.notifier);
|
||||
Future(() {
|
||||
fabMenuNotifier.state = FabMenuType.chat;
|
||||
fabMenuNotifier.setMenuType(FabMenuType.chat);
|
||||
});
|
||||
return () {
|
||||
// Clean up: reset FAB type to main
|
||||
final fabMenu = ref.read(fabMenuTypeProvider);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (fabMenuNotifier.state == FabMenuType.chat) {
|
||||
fabMenuNotifier.state = FabMenuType.main;
|
||||
if (fabMenu == FabMenuType.chat) {
|
||||
fabMenuNotifier.setMenuType(FabMenuType.main);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -521,7 +522,7 @@ class _ChatInvitesSheet extends HookConsumerWidget {
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/sphere/chat/invites/${invite.chatRoom!.id}/accept');
|
||||
ref.invalidate(chatroomInvitesProvider);
|
||||
ref.invalidate(chatRoomJoinedNotifierProvider);
|
||||
ref.invalidate(chatRoomJoinedProvider);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class EditChatScreen extends HookConsumerWidget {
|
||||
final isPublic = useState(true);
|
||||
final isCommunity = useState(false);
|
||||
|
||||
final chat = ref.watch(ChatRoomNotifierProvider(id));
|
||||
final chat = ref.watch(chatRoomProvider(id));
|
||||
|
||||
final joinedRealms = ref.watch(realmsJoinedProvider);
|
||||
final currentRealm = useState<SnRealm?>(null);
|
||||
|
||||
@@ -27,8 +27,8 @@ class PublicRoomPreview extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final messages = ref.watch(messagesNotifierProvider(id));
|
||||
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
|
||||
final messages = ref.watch(messagesProvider(id));
|
||||
final messagesNotifier = ref.read(messagesProvider(id).notifier);
|
||||
final scrollController = useScrollController();
|
||||
|
||||
final listController = useMemoized(() => ListController(), []);
|
||||
@@ -203,7 +203,7 @@ class PublicRoomPreview extends HookConsumerWidget {
|
||||
showLoadingModal(context);
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.post('/sphere/chat/${room.id}/members/me');
|
||||
ref.invalidate(ChatRoomIdentityNotifierProvider(id));
|
||||
ref.invalidate(chatRoomIdentityProvider(id));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
|
||||
@@ -48,11 +48,11 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final chatRoom = ref.watch(ChatRoomNotifierProvider(id));
|
||||
final chatIdentity = ref.watch(ChatRoomIdentityNotifierProvider(id));
|
||||
final isSyncing = ref.watch(isSyncingProvider);
|
||||
final onlineCount = ref.watch(chatOnlineCountNotifierProvider(id));
|
||||
final settings = ref.watch(appSettingsNotifierProvider);
|
||||
final chatRoom = ref.watch(chatRoomProvider(id));
|
||||
final chatIdentity = ref.watch(chatRoomIdentityProvider(id));
|
||||
final isSyncing = ref.watch(chatSyncingProvider);
|
||||
final onlineCount = ref.watch(chatOnlineCountProvider(id));
|
||||
final settings = ref.watch(appSettingsProvider);
|
||||
|
||||
if (chatIdentity.isLoading || chatRoom.isLoading) {
|
||||
return AppScaffold(
|
||||
@@ -100,9 +100,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
await apiClient.post(
|
||||
'/sphere/chat/${room.id}/members/me',
|
||||
);
|
||||
ref.invalidate(
|
||||
ChatRoomIdentityNotifierProvider(id),
|
||||
);
|
||||
ref.invalidate(chatRoomIdentityProvider(id));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
@@ -131,17 +129,15 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
appBar: AppBar(leading: const PageBackButton()),
|
||||
body: ResponseErrorWidget(
|
||||
error: error,
|
||||
onRetry: () => ref.refresh(ChatRoomNotifierProvider(id)),
|
||||
onRetry: () => ref.refresh(chatRoomProvider(id)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final messages = ref.watch(messagesNotifierProvider(id));
|
||||
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
|
||||
final chatSubscribeNotifier = ref.read(
|
||||
chatSubscribeNotifierProvider(id).notifier,
|
||||
);
|
||||
final messages = ref.watch(messagesProvider(id));
|
||||
final messagesNotifier = ref.read(messagesProvider(id).notifier);
|
||||
final chatSubscribeNotifier = ref.read(chatSubscribeProvider(id).notifier);
|
||||
|
||||
final messageController = useTextEditingController();
|
||||
final scrollController = useScrollController();
|
||||
@@ -384,7 +380,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
|
||||
// Convert selected message IDs to message data
|
||||
final selectedMessageData =
|
||||
messages.valueOrNull
|
||||
messages.value
|
||||
?.where((msg) => selectedMessages.value.contains(msg.id))
|
||||
.map(
|
||||
(msg) => {
|
||||
@@ -773,8 +769,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
'chatDetail',
|
||||
pathParameters: {'id': id},
|
||||
);
|
||||
if (result is SearchMessagesResult &&
|
||||
messages.valueOrNull != null) {
|
||||
if (result is SearchMessagesResult && messages.value != null) {
|
||||
final messageId = result.messageId;
|
||||
|
||||
// Jump to the message and trigger flash effect
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -40,8 +38,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final roomState = ref.watch(ChatRoomNotifierProvider(id));
|
||||
final roomIdentity = ref.watch(ChatRoomIdentityNotifierProvider(id));
|
||||
final roomState = ref.watch(chatRoomProvider(id));
|
||||
final roomIdentity = ref.watch(chatRoomIdentityProvider(id));
|
||||
final totalMessages = ref.watch(totalMessagesCountProvider(id));
|
||||
|
||||
const kNotifyLevelText = [
|
||||
@@ -57,7 +55,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
'/sphere/chat/$id/members/me/notify',
|
||||
data: {'notify_level': level},
|
||||
);
|
||||
ref.invalidate(ChatRoomIdentityNotifierProvider(id));
|
||||
ref.invalidate(chatRoomIdentityProvider(id));
|
||||
if (context.mounted) {
|
||||
showSnackBar(
|
||||
'chatNotifyLevelUpdated'.tr(args: [kNotifyLevelText[level].tr()]),
|
||||
@@ -75,7 +73,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
'/sphere/chat/$id/members/me/notify',
|
||||
data: {'break_until': until.toUtc().toIso8601String()},
|
||||
);
|
||||
ref.invalidate(ChatRoomNotifierProvider(id));
|
||||
ref.invalidate(chatRoomIdentityProvider(id));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
@@ -440,8 +438,8 @@ class _ChatRoomActionMenu extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final chatIdentity = ref.watch(ChatRoomIdentityNotifierProvider(id));
|
||||
final chatRoom = ref.watch(ChatRoomNotifierProvider(id));
|
||||
final chatIdentity = ref.watch(chatRoomIdentityProvider(id));
|
||||
final chatRoom = ref.watch(chatRoomProvider(id));
|
||||
|
||||
final isManagable =
|
||||
chatIdentity.value?.accountId == chatRoom.value?.accountId ||
|
||||
@@ -462,7 +460,7 @@ class _ChatRoomActionMenu extends HookConsumerWidget {
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
// Invalidate to refresh room data after edit
|
||||
ref.invalidate(ChatRoomNotifierProvider(id));
|
||||
ref.invalidate(chatMemberListProvider(id));
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -498,7 +496,7 @@ class _ChatRoomActionMenu extends HookConsumerWidget {
|
||||
if (confirm) {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.delete('/sphere/chat/$id');
|
||||
ref.invalidate(chatRoomJoinedNotifierProvider);
|
||||
ref.invalidate(chatRoomJoinedProvider);
|
||||
if (context.mounted) {
|
||||
context.pop();
|
||||
}
|
||||
@@ -531,7 +529,7 @@ class _ChatRoomActionMenu extends HookConsumerWidget {
|
||||
if (confirm) {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.delete('/sphere/chat/$id/members/me');
|
||||
ref.invalidate(chatRoomJoinedNotifierProvider);
|
||||
ref.invalidate(chatRoomJoinedProvider);
|
||||
if (context.mounted) {
|
||||
context.pop();
|
||||
}
|
||||
@@ -554,63 +552,17 @@ sealed class ChatRoomMemberState with _$ChatRoomMemberState {
|
||||
}) = _ChatRoomMemberState;
|
||||
}
|
||||
|
||||
final chatMemberStateProvider = StateNotifierProvider.family<
|
||||
ChatMemberNotifier,
|
||||
ChatRoomMemberState,
|
||||
String
|
||||
>((ref, roomId) {
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
return ChatMemberNotifier(apiClient, roomId);
|
||||
});
|
||||
final chatMemberListProvider = AsyncNotifierProvider.autoDispose.family(
|
||||
ChatMemberListNotifier.new,
|
||||
);
|
||||
|
||||
class ChatMemberNotifier extends StateNotifier<ChatRoomMemberState> {
|
||||
final String roomId;
|
||||
final Dio _apiClient;
|
||||
|
||||
ChatMemberNotifier(this._apiClient, this.roomId)
|
||||
: super(const ChatRoomMemberState(members: [], isLoading: false, total: 0));
|
||||
|
||||
Future<void> loadMore({int offset = 0, int take = 20}) async {
|
||||
if (state.isLoading) return;
|
||||
if (state.total > 0 && state.members.length >= state.total) return;
|
||||
|
||||
state = state.copyWith(isLoading: true, error: null);
|
||||
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'/sphere/chat/$roomId/members',
|
||||
queryParameters: {'offset': offset, 'take': take},
|
||||
);
|
||||
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
final List<dynamic> data = response.data;
|
||||
final members = data.map((e) => SnChatMember.fromJson(e)).toList();
|
||||
|
||||
state = state.copyWith(
|
||||
members: [...state.members, ...members],
|
||||
total: total,
|
||||
isLoading: false,
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(error: e.toString(), isLoading: false);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
state = const ChatRoomMemberState(members: [], isLoading: false, total: 0);
|
||||
}
|
||||
}
|
||||
|
||||
final chatMemberListNotifierProvider = AsyncNotifierProvider.autoDispose
|
||||
.family<ChatMemberListNotifier, List<SnChatMember>, String>(
|
||||
ChatMemberListNotifier.new,
|
||||
);
|
||||
|
||||
class ChatMemberListNotifier
|
||||
extends AutoDisposeFamilyAsyncNotifier<List<SnChatMember>, String>
|
||||
with FamilyAsyncPaginationController<SnChatMember, String> {
|
||||
class ChatMemberListNotifier extends AsyncNotifier<List<SnChatMember>>
|
||||
with AsyncPaginationController<SnChatMember> {
|
||||
static const pageSize = 20;
|
||||
|
||||
final String arg;
|
||||
ChatMemberListNotifier(this.arg);
|
||||
|
||||
@override
|
||||
Future<List<SnChatMember>> fetch() async {
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
@@ -640,26 +592,15 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final memberListProvider = chatMemberListNotifierProvider(roomId);
|
||||
final memberNotifier = ref.read(chatMemberListProvider(roomId).notifier);
|
||||
|
||||
// For backward compatibility and to show total count in the header
|
||||
final memberState = ref.watch(chatMemberStateProvider(roomId));
|
||||
final memberNotifier = ref.read(chatMemberStateProvider(roomId).notifier);
|
||||
|
||||
final roomIdentity = ref.watch(ChatRoomIdentityNotifierProvider(roomId));
|
||||
final chatRoom = ref.watch(ChatRoomNotifierProvider(roomId));
|
||||
final roomIdentity = ref.watch(chatRoomIdentityProvider(roomId));
|
||||
final chatRoom = ref.watch(chatRoomProvider(roomId));
|
||||
|
||||
final isManagable =
|
||||
chatRoom.value?.accountId == roomIdentity.value?.accountId ||
|
||||
chatRoom.value?.type == 1;
|
||||
|
||||
useEffect(() {
|
||||
Future(() {
|
||||
memberNotifier.loadMore();
|
||||
});
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
Future<void> invitePerson() async {
|
||||
final result = await showModalBottomSheet(
|
||||
context: context,
|
||||
@@ -674,10 +615,7 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
'/sphere/chat/invites/$roomId',
|
||||
data: {'related_user_id': result.id, 'role': 0},
|
||||
);
|
||||
// Refresh both providers
|
||||
memberNotifier.reset();
|
||||
await memberNotifier.loadMore();
|
||||
ref.invalidate(memberListProvider);
|
||||
memberNotifier.refresh();
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
@@ -694,7 +632,7 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'members'.plural(memberState.total),
|
||||
'members'.plural(memberNotifier.totalCount ?? 0),
|
||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.5,
|
||||
@@ -709,10 +647,7 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.refresh),
|
||||
onPressed: () {
|
||||
// Refresh both providers
|
||||
memberNotifier.reset();
|
||||
memberNotifier.loadMore();
|
||||
ref.invalidate(memberListProvider);
|
||||
memberNotifier.refresh();
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@@ -726,8 +661,8 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: PaginationList(
|
||||
provider: memberListProvider,
|
||||
notifier: memberListProvider.notifier,
|
||||
provider: chatMemberListProvider(roomId),
|
||||
notifier: chatMemberListProvider(roomId).notifier,
|
||||
itemBuilder: (context, idx, member) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||
@@ -770,9 +705,7 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
'/sphere/chat/$roomId/members/${member.accountId}',
|
||||
);
|
||||
// Refresh both providers
|
||||
memberNotifier.reset();
|
||||
memberNotifier.loadMore();
|
||||
ref.invalidate(memberListProvider);
|
||||
memberNotifier.refresh();
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
|
||||
@@ -6,148 +6,75 @@ part of 'room_detail.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$totalMessagesCountHash() =>
|
||||
r'd55f1507aba2acdce5e468c1c2e15dba7640c571';
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
/// 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));
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
@ProviderFor(totalMessagesCount)
|
||||
const totalMessagesCountProvider = TotalMessagesCountFamily();
|
||||
const totalMessagesCountProvider = TotalMessagesCountFamily._();
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
class TotalMessagesCountFamily extends Family<AsyncValue<int>> {
|
||||
/// See also [totalMessagesCount].
|
||||
const TotalMessagesCountFamily();
|
||||
final class TotalMessagesCountProvider
|
||||
extends $FunctionalProvider<AsyncValue<int>, int, FutureOr<int>>
|
||||
with $FutureModifier<int>, $FutureProvider<int> {
|
||||
const TotalMessagesCountProvider._({
|
||||
required TotalMessagesCountFamily super.from,
|
||||
required String super.argument,
|
||||
}) : super(
|
||||
retry: null,
|
||||
name: r'totalMessagesCountProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
TotalMessagesCountProvider call(String roomId) {
|
||||
return TotalMessagesCountProvider(roomId);
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$totalMessagesCountHash();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return r'totalMessagesCountProvider'
|
||||
''
|
||||
'($argument)';
|
||||
}
|
||||
|
||||
@$internal
|
||||
@override
|
||||
TotalMessagesCountProvider getProviderOverride(
|
||||
covariant TotalMessagesCountProvider provider,
|
||||
) {
|
||||
return call(provider.roomId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
$FutureProviderElement<int> $createElement($ProviderPointer pointer) =>
|
||||
$FutureProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'totalMessagesCountProvider';
|
||||
}
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
class TotalMessagesCountProvider extends AutoDisposeFutureProvider<int> {
|
||||
/// See also [totalMessagesCount].
|
||||
TotalMessagesCountProvider(String roomId)
|
||||
: this._internal(
|
||||
(ref) => totalMessagesCount(ref as TotalMessagesCountRef, roomId),
|
||||
from: totalMessagesCountProvider,
|
||||
name: r'totalMessagesCountProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$totalMessagesCountHash,
|
||||
dependencies: TotalMessagesCountFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
TotalMessagesCountFamily._allTransitiveDependencies,
|
||||
roomId: roomId,
|
||||
);
|
||||
|
||||
TotalMessagesCountProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.roomId,
|
||||
}) : super.internal();
|
||||
|
||||
final String roomId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<int> Function(TotalMessagesCountRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: TotalMessagesCountProvider._internal(
|
||||
(ref) => create(ref as TotalMessagesCountRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
roomId: roomId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<int> createElement() {
|
||||
return _TotalMessagesCountProviderElement(this);
|
||||
FutureOr<int> create(Ref ref) {
|
||||
final argument = this.argument as String;
|
||||
return totalMessagesCount(ref, argument);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is TotalMessagesCountProvider && other.roomId == roomId;
|
||||
return other is TotalMessagesCountProvider && other.argument == argument;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, roomId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
return argument.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin TotalMessagesCountRef on AutoDisposeFutureProviderRef<int> {
|
||||
/// The parameter `roomId` of this provider.
|
||||
String get roomId;
|
||||
}
|
||||
String _$totalMessagesCountHash() =>
|
||||
r'd55f1507aba2acdce5e468c1c2e15dba7640c571';
|
||||
|
||||
class _TotalMessagesCountProviderElement
|
||||
extends AutoDisposeFutureProviderElement<int>
|
||||
with TotalMessagesCountRef {
|
||||
_TotalMessagesCountProviderElement(super.provider);
|
||||
final class TotalMessagesCountFamily extends $Family
|
||||
with $FunctionalFamilyOverride<FutureOr<int>, String> {
|
||||
const TotalMessagesCountFamily._()
|
||||
: super(
|
||||
retry: null,
|
||||
name: r'totalMessagesCountProvider',
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
isAutoDispose: true,
|
||||
);
|
||||
|
||||
TotalMessagesCountProvider call(String roomId) =>
|
||||
TotalMessagesCountProvider._(argument: roomId, from: this);
|
||||
|
||||
@override
|
||||
String get roomId => (origin as TotalMessagesCountProvider).roomId;
|
||||
String toString() => r'totalMessagesCountProvider';
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@@ -124,9 +124,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
||||
// Debounce timer for search optimization
|
||||
final debounceTimer = useRef<Timer?>(null);
|
||||
|
||||
final messagesNotifier = ref.read(
|
||||
messagesNotifierProvider(roomId).notifier,
|
||||
);
|
||||
final messagesNotifier = ref.read(messagesProvider(roomId).notifier);
|
||||
|
||||
// Optimized search function with debouncing
|
||||
void performSearch(String query) async {
|
||||
@@ -180,7 +178,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// Clear flashing messages when entering search screen
|
||||
ref.read(flashingMessagesProvider.notifier).state = {};
|
||||
ref.read(flashingMessagesProvider.notifier).clear();
|
||||
});
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:island/database/message.dart';
|
||||
import 'package:island/models/chat.dart';
|
||||
import 'package:island/widgets/chat/message_item.dart';
|
||||
|
||||
// Provider to track animated messages to prevent replay
|
||||
final animatedMessagesProvider = StateProvider<Set<String>>((ref) => {});
|
||||
final animatedMessagesProvider =
|
||||
NotifierProvider<AnimatedMessagesNotifier, Set<String>>(
|
||||
AnimatedMessagesNotifier.new,
|
||||
);
|
||||
|
||||
class MessageItemWrapper extends HookConsumerWidget {
|
||||
class AnimatedMessagesNotifier extends Notifier<Set<String>> {
|
||||
@override
|
||||
Set<String> build() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void addMessage(String messageId) {
|
||||
state = {...state, messageId};
|
||||
}
|
||||
}
|
||||
|
||||
class MessageItemWrapper extends ConsumerWidget {
|
||||
final LocalChatMessage message;
|
||||
final int index;
|
||||
final bool isLastInGroup;
|
||||
@@ -78,9 +92,7 @@ class MessageItemWrapper extends HookConsumerWidget {
|
||||
onEnd: () {
|
||||
// Mark as animated
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
ref
|
||||
.read(animatedMessagesProvider.notifier)
|
||||
.update((state) => {...state, message.id});
|
||||
ref.read(animatedMessagesProvider.notifier).addMessage(message.id);
|
||||
});
|
||||
},
|
||||
child: child,
|
||||
|
||||
Reference in New Issue
Block a user