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
This commit is contained in:
Freek van de Ven 2025-02-11 14:42:26 +01:00 committed by Freek van de Ven
parent ea3ea0a21d
commit 9af9bc8078
6 changed files with 101 additions and 49 deletions

View file

@ -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

View file

@ -11,4 +11,8 @@ abstract class UserRepositoryInterface {
/// Get all the users.
/// Returns a list of [UserModel] stream.
Stream<List<UserModel>> getAllUsers();
/// Get all the users for the given [chatId].
/// Returns a list of [UserModel] stream.
Stream<List<UserModel>> getAllUsersForChat({required String chatId});
}

View file

@ -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<List<MessageModel>> _messageController =
BehaviorSubject<List<MessageModel>>();
final List<ChatModel> _chats = [];
final Map<String, List<MessageModel>> _messages = {};
@override
Future<void> createChat({
required List<String> 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<void> 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<ChatModel> 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<List<ChatModel>?> 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<MessageModel>.from(_messages[chatId] ?? []);
var messages = List<MessageModel>.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<MessageModel>.from(_messages[chatId] ?? []);
var messages = List<MessageModel>.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

View file

@ -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<ChatModel> chats = [];
/// All the messages of the local memory database mapped by chat id
final Map<String, List<MessageModel>> chatMessages = {};
/// All the users of the local memory database
final List<UserModel> 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",
),
];

View file

@ -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<List<UserModel>> _usersController =
BehaviorSubject<List<UserModel>>();
final List<UserModel> _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<UserModel> getUser({
required String userId,
@ -49,8 +23,28 @@ class LocalUserRepository implements UserRepositoryInterface {
@override
Stream<List<UserModel>> getAllUsers() {
_usersController.add(_users);
_usersController.add(users);
return _usersController.stream;
}
@override
Stream<List<UserModel>> 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(),
);
}

View file

@ -33,4 +33,21 @@ class FirebaseUserRepository implements UserRepositoryInterface {
snapshot.data()!,
),
);
@override
Stream<List<UserModel>> 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(),
);
}