feat: integrate ErrorService for consistent error display and standardize bloc error messages.

This commit is contained in:
Van Leemput Dayron
2025-12-02 13:59:40 +01:00
parent 1e70b9e09f
commit 6757cb013a
24 changed files with 927 additions and 608 deletions

View File

@@ -19,10 +19,10 @@
/// Example usage:
/// ```dart
/// final messageBloc = MessageBloc();
///
///
/// // Load messages for a group
/// messageBloc.add(LoadMessages('groupId123'));
///
///
/// // Send a message
/// messageBloc.add(SendMessage(
/// groupId: 'groupId123',
@@ -30,7 +30,7 @@
/// senderId: 'userId123',
/// senderName: 'John Doe',
/// ));
///
///
/// // React to a message
/// messageBloc.add(ReactToMessage(
/// groupId: 'groupId123',
@@ -40,6 +40,7 @@
/// ));
/// ```
library;
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/message.dart';
@@ -52,23 +53,23 @@ import 'message_state.dart';
class MessageBloc extends Bloc<MessageEvent, MessageState> {
/// Service for message operations and business logic
final MessageService _messageService;
/// Subscription to message stream for real-time updates
StreamSubscription<List<Message>>? _messagesSubscription;
/// Constructor for MessageBloc.
///
///
/// Initializes the bloc with an optional message service. If no service is provided,
/// creates a default MessageService with MessageRepository. Sets up event handlers
/// for all message-related operations.
///
///
/// Args:
/// [messageService]: Optional service for message operations (auto-created if null)
MessageBloc({MessageService? messageService})
: _messageService = messageService ?? MessageService(
messageRepository: MessageRepository(),
),
super(MessageInitial()) {
: _messageService =
messageService ??
MessageService(messageRepository: MessageRepository()),
super(MessageInitial()) {
on<LoadMessages>(_onLoadMessages);
on<SendMessage>(_onSendMessage);
on<DeleteMessage>(_onDeleteMessage);
@@ -79,10 +80,10 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
}
/// Handles [LoadMessages] events.
///
///
/// Loads messages for a specific group with real-time updates via stream subscription.
/// Cancels any existing subscription before creating a new one to prevent memory leaks.
///
///
/// Args:
/// [event]: The LoadMessages event containing the group ID
/// [emit]: State emitter function
@@ -101,31 +102,28 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
add(_MessagesUpdated(messages: messages, groupId: event.groupId));
},
onError: (error) {
add(_MessagesError('Error loading messages: $error'));
add(const _MessagesError('Impossible de charger les messages'));
},
);
}
/// Handles [_MessagesUpdated] events.
///
///
/// Processes real-time updates from the message stream, emitting the
/// updated message list with the associated group ID.
///
///
/// Args:
/// [event]: The _MessagesUpdated event containing messages and group ID
/// [emit]: State emitter function
void _onMessagesUpdated(
_MessagesUpdated event,
Emitter<MessageState> emit,
) {
void _onMessagesUpdated(_MessagesUpdated event, Emitter<MessageState> emit) {
emit(MessagesLoaded(messages: event.messages, groupId: event.groupId));
}
/// Handles [SendMessage] events.
///
///
/// Sends a new message to a group chat. The stream subscription will
/// automatically update the UI with the new message, so no state is emitted here.
///
///
/// Args:
/// [event]: The SendMessage event containing message details
/// [emit]: State emitter function
@@ -142,15 +140,15 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
senderName: event.senderName,
);
} catch (e) {
emit(MessageError('Error sending message: $e'));
emit(const MessageError('Impossible d\'envoyer le message'));
}
}
/// Handles [DeleteMessage] events.
///
///
/// Deletes a message from the group chat. The Firestore stream will
/// automatically update the UI, so no state is emitted here unless there's an error.
///
///
/// Args:
/// [event]: The DeleteMessage event containing group ID and message ID
/// [emit]: State emitter function
@@ -166,15 +164,15 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
messageId: event.messageId,
);
} catch (e) {
emit(MessageError('Error deleting message: $e'));
emit(const MessageError('Impossible de supprimer le message'));
}
}
/// Handles [UpdateMessage] events.
///
///
/// Updates/edits an existing message in the group chat. The Firestore stream will
/// automatically update the UI with the edited message, so no state is emitted here.
///
///
/// Args:
/// [event]: The UpdateMessage event containing message ID and new text
/// [emit]: State emitter function
@@ -191,15 +189,15 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
newText: event.newText,
);
} catch (e) {
emit(MessageError('Error updating message: $e'));
emit(const MessageError('Impossible de modifier le message'));
}
}
/// Handles [ReactToMessage] events.
///
///
/// Adds an emoji reaction to a message. The Firestore stream will
/// automatically update the UI with the new reaction, so no state is emitted here.
///
///
/// Args:
/// [event]: The ReactToMessage event containing message ID, user ID, and reaction
/// [emit]: State emitter function
@@ -217,15 +215,15 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
reaction: event.reaction,
);
} catch (e) {
emit(MessageError('Error adding reaction: $e'));
emit(const MessageError('Impossible d\'ajouter la réaction'));
}
}
/// Handles [RemoveReaction] events.
///
///
/// Removes a user's reaction from a message. The Firestore stream will
/// automatically update the UI with the removed reaction, so no state is emitted here.
///
///
/// Args:
/// [event]: The RemoveReaction event containing message ID and user ID
/// [emit]: State emitter function
@@ -242,12 +240,12 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
userId: event.userId,
);
} catch (e) {
emit(MessageError('Error removing reaction: $e'));
emit(const MessageError('Impossible de supprimer la réaction'));
}
}
/// Cleans up resources when the bloc is closed.
///
///
/// Cancels the message stream subscription to prevent memory leaks
/// and ensure proper disposal of resources.
@override
@@ -258,32 +256,29 @@ class MessageBloc extends Bloc<MessageEvent, MessageState> {
}
/// Private event for handling real-time message updates from streams.
///
///
/// This internal event is used to process updates from the message stream
/// subscription and emit appropriate states based on the received data.
class _MessagesUpdated extends MessageEvent {
/// List of messages received from the stream
final List<Message> messages;
/// Group ID associated with the messages
final String groupId;
/// Creates a _MessagesUpdated event.
///
///
/// Args:
/// [messages]: List of messages from the stream update
/// [groupId]: ID of the group these messages belong to
const _MessagesUpdated({
required this.messages,
required this.groupId,
});
const _MessagesUpdated({required this.messages, required this.groupId});
@override
List<Object?> get props => [messages, groupId];
}
/// Private event for handling message stream errors.
///
///
/// This internal event is used to process errors from the message stream
/// subscription and emit appropriate error states.
class _MessagesError extends MessageEvent {
@@ -291,7 +286,7 @@ class _MessagesError extends MessageEvent {
final String error;
/// Creates a _MessagesError event.
///
///
/// Args:
/// [error]: Error message from the stream failure
const _MessagesError(this.error);