From 9af9bc8078194dd87da7825f9063aa9dd5b1e90d Mon Sep 17 00:00:00 2001 From: Freek van de Ven Date: Tue, 11 Feb 2025 14:42:26 +0100 Subject: [PATCH] feat: add getAllUsersForChat to UserRepositoryInterface This allows to get all the users for a chat in one call instead of doing multiple seperate calls for every individual user of a chat --- CHANGELOG.md | 1 + .../interfaces/user_repository_interface.dart | 4 ++ .../lib/src/local/local_chat_repository.dart | 41 ++++++++------- .../lib/src/local/local_memory_db.dart | 37 ++++++++++++++ .../lib/src/local/local_user_repository.dart | 50 ++++++++----------- .../lib/src/firebase_user_repository.dart | 17 +++++++ 6 files changed, 101 insertions(+), 49 deletions(-) create mode 100644 packages/chat_repository_interface/lib/src/local/local_memory_db.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index fc15f1f..32ed672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added chatMessageBuilder to the userstory configuration to customize the chat messages - Update the default chat message builder to a new design - Added ChatScope that can be used to get the ChatService and ChatTranslations from the context. If you use individual components instead of the userstory you need to wrap them with the ChatScope. The options and service will be removed from all the component constructors. +- Added getAllUsersForChat to UserRepositoryInterface for fetching all users for a chat ## 4.0.0 - Move to the new user story architecture diff --git a/packages/chat_repository_interface/lib/src/interfaces/user_repository_interface.dart b/packages/chat_repository_interface/lib/src/interfaces/user_repository_interface.dart index 323d2d0..ad708a8 100644 --- a/packages/chat_repository_interface/lib/src/interfaces/user_repository_interface.dart +++ b/packages/chat_repository_interface/lib/src/interfaces/user_repository_interface.dart @@ -11,4 +11,8 @@ abstract class UserRepositoryInterface { /// Get all the users. /// Returns a list of [UserModel] stream. Stream> getAllUsers(); + + /// Get all the users for the given [chatId]. + /// Returns a list of [UserModel] stream. + Stream> getAllUsersForChat({required String chatId}); } diff --git a/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart b/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart index 0b93b05..74f1061 100644 --- a/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart +++ b/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart @@ -2,6 +2,7 @@ import "dart:async"; import "dart:typed_data"; import "package:chat_repository_interface/chat_repository_interface.dart"; +import "package:chat_repository_interface/src/local/local_memory_db.dart"; import "package:collection/collection.dart"; import "package:rxdart/rxdart.dart"; @@ -19,9 +20,6 @@ class LocalChatRepository implements ChatRepositoryInterface { final StreamController> _messageController = BehaviorSubject>(); - final List _chats = []; - final Map> _messages = {}; - @override Future createChat({ required List users, @@ -40,8 +38,8 @@ class LocalChatRepository implements ChatRepositoryInterface { imageUrl: imageUrl, ); - _chats.add(chat); - _chatsController.add(_chats); + chats.add(chat); + _chatsController.add(chats); if (messages != null) { for (var message in messages) { @@ -62,11 +60,11 @@ class LocalChatRepository implements ChatRepositoryInterface { Future updateChat({ required ChatModel chat, }) async { - var index = _chats.indexWhere((e) => e.id == chat.id); + var index = chats.indexWhere((e) => e.id == chat.id); if (index != -1) { - _chats[index] = chat; - _chatsController.add(_chats); + chats[index] = chat; + _chatsController.add(chats); } } @@ -75,8 +73,8 @@ class LocalChatRepository implements ChatRepositoryInterface { required String chatId, }) async { try { - _chats.removeWhere((e) => e.id == chatId); - _chatsController.add(_chats); + chats.removeWhere((e) => e.id == chatId); + _chatsController.add(chats); } on Exception catch (_) { rethrow; } @@ -86,7 +84,7 @@ class LocalChatRepository implements ChatRepositoryInterface { Stream getChat({ required String chatId, }) { - var chat = _chats.firstWhereOrNull((e) => e.id == chatId); + var chat = chats.firstWhereOrNull((e) => e.id == chatId); if (chat != null) { _chatController.add(chat); @@ -103,7 +101,7 @@ class LocalChatRepository implements ChatRepositoryInterface { Stream?> getChats({ required String userId, }) { - _chatsController.add(_chats); + _chatsController.add(chats); return _chatsController.stream; } @@ -117,10 +115,10 @@ class LocalChatRepository implements ChatRepositoryInterface { }) { ChatModel? chat; - chat = _chats.firstWhereOrNull((e) => e.id == chatId); + chat = chats.firstWhereOrNull((e) => e.id == chatId); if (chat != null) { - var messages = List.from(_messages[chatId] ?? []); + var messages = List.from(chatMessages[chatId] ?? []); messages.sort((a, b) => a.timestamp.compareTo(b.timestamp)); @@ -171,7 +169,8 @@ class LocalChatRepository implements ChatRepositoryInterface { required String chatId, required String messageId, }) { - var message = _messages[chatId]?.firstWhereOrNull((e) => e.id == messageId); + var message = + chatMessages[chatId]?.firstWhereOrNull((e) => e.id == messageId); return Stream.value(message); } @@ -196,13 +195,13 @@ class LocalChatRepository implements ChatRepositoryInterface { imageUrl: imageUrl, ); - var chat = _chats.firstWhereOrNull((e) => e.id == chatId); + var chat = chats.firstWhereOrNull((e) => e.id == chatId); if (chat == null) throw Exception("Chat not found"); - var messages = List.from(_messages[chatId] ?? []); + var messages = List.from(chatMessages[chatId] ?? []); messages.add(message); - _messages[chatId] = messages; + chatMessages[chatId] = messages; var newChat = chat.copyWith( lastMessage: messageId, @@ -210,10 +209,10 @@ class LocalChatRepository implements ChatRepositoryInterface { lastUsed: DateTime.now(), ); - _chats[_chats.indexWhere((e) => e.id == chatId)] = newChat; + chats[chats.indexWhere((e) => e.id == chatId)] = newChat; - _chatsController.add(_chats); - _messageController.add(_messages[chatId] ?? []); + _chatsController.add(chats); + _messageController.add(chatMessages[chatId] ?? []); } @override diff --git a/packages/chat_repository_interface/lib/src/local/local_memory_db.dart b/packages/chat_repository_interface/lib/src/local/local_memory_db.dart new file mode 100644 index 0000000..043b066 --- /dev/null +++ b/packages/chat_repository_interface/lib/src/local/local_memory_db.dart @@ -0,0 +1,37 @@ +import "package:chat_repository_interface/src/models/chat_model.dart"; +import "package:chat_repository_interface/src/models/message_model.dart"; +import "package:chat_repository_interface/src/models/user_model.dart"; + +/// All the chats of the local memory database +final List chats = []; + +/// All the messages of the local memory database mapped by chat id +final Map> chatMessages = {}; + +/// All the users of the local memory database +final List users = [ + const UserModel( + id: "1", + firstName: "John", + lastName: "Doe", + imageUrl: "https://picsum.photos/200/300", + ), + const UserModel( + id: "2", + firstName: "Jane", + lastName: "Doe", + imageUrl: "https://picsum.photos/200/300", + ), + const UserModel( + id: "3", + firstName: "Frans", + lastName: "Timmermans", + imageUrl: "https://picsum.photos/200/300", + ), + const UserModel( + id: "4", + firstName: "Hendrik-Jan", + lastName: "De derde", + imageUrl: "https://picsum.photos/200/300", + ), +]; diff --git a/packages/chat_repository_interface/lib/src/local/local_user_repository.dart b/packages/chat_repository_interface/lib/src/local/local_user_repository.dart index f68fbc2..65c7706 100644 --- a/packages/chat_repository_interface/lib/src/local/local_user_repository.dart +++ b/packages/chat_repository_interface/lib/src/local/local_user_repository.dart @@ -1,6 +1,7 @@ import "dart:async"; import "package:chat_repository_interface/src/interfaces/user_repository_interface.dart"; +import "package:chat_repository_interface/src/local/local_memory_db.dart"; import "package:chat_repository_interface/src/models/user_model.dart"; import "package:rxdart/rxdart.dart"; @@ -9,33 +10,6 @@ class LocalUserRepository implements UserRepositoryInterface { final StreamController> _usersController = BehaviorSubject>(); - final List _users = [ - const UserModel( - id: "1", - firstName: "John", - lastName: "Doe", - imageUrl: "https://picsum.photos/200/300", - ), - const UserModel( - id: "2", - firstName: "Jane", - lastName: "Doe", - imageUrl: "https://picsum.photos/200/300", - ), - const UserModel( - id: "3", - firstName: "Frans", - lastName: "Timmermans", - imageUrl: "https://picsum.photos/200/300", - ), - const UserModel( - id: "4", - firstName: "Hendrik-Jan", - lastName: "De derde", - imageUrl: "https://picsum.photos/200/300", - ), - ]; - @override Stream getUser({ required String userId, @@ -49,8 +23,28 @@ class LocalUserRepository implements UserRepositoryInterface { @override Stream> getAllUsers() { - _usersController.add(_users); + _usersController.add(users); return _usersController.stream; } + + @override + Stream> getAllUsersForChat({ + required String chatId, + }) => + Stream.value( + chats + .firstWhere( + (chat) => chat.id == chatId, + orElse: () => throw Exception("Chat not found"), + ) + .users + .map( + (userId) => users.firstWhere( + (user) => user.id == userId, + orElse: () => throw Exception("User not found"), + ), + ) + .toList(), + ); } diff --git a/packages/firebase_chat_repository/lib/src/firebase_user_repository.dart b/packages/firebase_chat_repository/lib/src/firebase_user_repository.dart index 3426383..d014438 100644 --- a/packages/firebase_chat_repository/lib/src/firebase_user_repository.dart +++ b/packages/firebase_chat_repository/lib/src/firebase_user_repository.dart @@ -33,4 +33,21 @@ class FirebaseUserRepository implements UserRepositoryInterface { snapshot.data()!, ), ); + + @override + Stream> getAllUsersForChat({required String chatId}) => + _firestore + .collection(_userCollection) + .where("chats", arrayContains: chatId) + .snapshots() + .map( + (querySnapshot) => querySnapshot.docs + .map( + (doc) => UserModel.fromMap( + doc.id, + doc.data(), + ), + ) + .toList(), + ); }