feat(chat-options): add pending messages option

This commit is contained in:
Kiril Tijsma 2025-03-11 10:26:42 +01:00
parent 9d7ca39f49
commit 6fbe1e67d2
8 changed files with 72 additions and 26 deletions

View file

@ -73,6 +73,12 @@ abstract class ChatRepositoryInterface {
required MessageModel firstMessage,
});
/// Function that provides the next message id
Future<String> getNextMessageId({
required String userId,
required String chatId,
});
/// Send a message with the given parameters.
/// [chatId] is the chat id.
/// [senderId] is the sender id.

View file

@ -208,6 +208,13 @@ class LocalChatRepository implements ChatRepositoryInterface {
return Stream.value(message);
}
@override
Future<String> getNextMessageId({
required String userId,
required String chatId,
}) async =>
"$chatId-$userId-${DateTime.now()}";
@override
Future<void> sendMessage({
required String chatId,

View file

@ -25,9 +25,9 @@ class ChatService {
PendingMessageRepositoryInterface? pendingMessageRepository,
UserRepositoryInterface? userRepository,
}) : chatRepository = chatRepository ?? LocalChatRepository(),
userRepository = userRepository ?? LocalUserRepository(),
pendingMessageRepository =
pendingMessageRepository ?? LocalPendingMessageRepository(),
userRepository = userRepository ?? LocalUserRepository();
pendingMessageRepository ?? LocalPendingMessageRepository();
/// The user ID of the person currently looking at the chat
final String userId;
@ -200,12 +200,15 @@ class ChatService {
Future<void> sendMessage({
required String chatId,
required String senderId,
required String messageId,
String? presetMessageId,
String? text,
String? messageType,
String? imageUrl,
Uint8List? imageData,
}) async {
var messageId = presetMessageId ??
await chatRepository.getNextMessageId(userId: userId, chatId: chatId);
await pendingMessageRepository.createMessage(
chatId: chatId,
senderId: senderId,
@ -239,6 +242,32 @@ class ChatService {
);
}
/// Method for sending an image and a message at the same time.
Future<void> sendImageMessage({
required String chatId,
required String userId,
required Uint8List data,
}) async {
var messageId = await chatRepository.getNextMessageId(
userId: userId,
chatId: chatId,
);
var path = await uploadImage(
path: "chats/$messageId",
image: data,
chatId: chatId,
);
await sendMessage(
presetMessageId: messageId,
chatId: chatId,
senderId: userId,
imageUrl: path,
imageData: data,
);
}
/// Delete the chat with the given parameters.
/// [chatId] is the chat id.
Future<void> deleteChat({

View file

@ -140,6 +140,13 @@ class FirebaseChatRepository implements ChatRepositoryInterface {
}
}
@override
Future<String> getNextMessageId({
required String userId,
required String chatId,
}) async =>
"$chatId-$userId-${DateTime.now()}";
@override
Future<void> sendMessage({
required String chatId,

View file

@ -29,12 +29,19 @@ class ChatOptions {
this.timeIndicatorOptions = const ChatTimeIndicatorOptions(),
ChatRepositoryInterface? chatRepository,
UserRepositoryInterface? userRepository,
PendingMessageRepositoryInterface? pendingMessagesRepository,
}) : chatRepository = chatRepository ?? LocalChatRepository(),
userRepository = userRepository ?? LocalUserRepository();
userRepository = userRepository ?? LocalUserRepository(),
pendingMessagesRepository =
pendingMessagesRepository ?? LocalPendingMessageRepository();
/// The implementation for communication with persistance layer for chats
final ChatRepositoryInterface chatRepository;
/// The implementation for communication with persistance layer
/// for pending messages
final PendingMessageRepositoryInterface pendingMessagesRepository;
/// The implementation for communication with persistance layer for users
final UserRepositoryInterface userRepository;

View file

@ -83,6 +83,7 @@ class _FlutterChatEntryWidgetState extends State<FlutterChatEntryWidget> {
userId: widget.userId,
chatRepository: widget.options?.chatRepository,
userRepository: widget.options?.userRepository,
pendingMessageRepository: widget.options?.pendingMessagesRepository,
);
}

View file

@ -94,6 +94,7 @@ abstract class _BaseChatNavigatorUserstory extends HookWidget {
userId: userId,
chatRepository: options.chatRepository,
userRepository: options.userRepository,
pendingMessageRepository: options.pendingMessagesRepository,
),
[userId, options],
);

View file

@ -50,28 +50,16 @@ MaterialPageRoute chatDetailRoute({
chatId: chatId,
onExit: onExit,
onReadChat: (chat) async => chatService.markAsRead(chatId: chat.id),
onUploadImage: (data) async {
var path = await chatService.uploadImage(
path: "chats/$chatId-$userId-${DateTime.now()}",
image: data,
chatId: chatId,
);
await chatService.sendMessage(
messageId: "$chatId-$userId-${DateTime.now()}",
chatId: chatId,
senderId: userId,
imageUrl: path,
imageData: data,
);
},
onMessageSubmit: (text) async {
await chatService.sendMessage(
messageId: "$chatId-$userId-${DateTime.now()}",
chatId: chatId,
senderId: userId,
text: text,
);
},
onUploadImage: (data) async => chatService.sendImageMessage(
chatId: chatId,
userId: userId,
data: data,
),
onMessageSubmit: (text) async => chatService.sendMessage(
chatId: chatId,
senderId: userId,
text: text,
),
onPressChatTitle: (chat) async {
if (chat.isGroupChat) {
await _routeToScreen(