Files
forkmessager/client-mobile/lib/features/chat/presentation/bloc/chat_bloc.dart
T

93 lines
3.4 KiB
Dart

import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../domain/entities/chat.dart';
import '../../domain/entities/message.dart';
import '../../domain/repositories/chat_repository.dart';
import 'chat_event.dart';
import 'chat_state.dart';
class ChatBloc extends Bloc<ChatEvent, ChatState> {
final ChatRepository chatRepository;
StreamSubscription? _messageSubscription;
ChatBloc({required this.chatRepository}) : super(const ChatState.initial()) {
on<ChatEventStarted>(_onStarted);
on<ChatEventChatsLoaded>(_onChatsLoaded);
on<ChatEventChatSelected>(_onChatSelected);
on<ChatEventMessagesRequested>(_onMessagesRequested);
on<ChatEventMessageSent>(_onMessageSent);
on<ChatEventFavoritesRequested>(_onFavoritesRequested);
_messageSubscription = chatRepository.messageStream.listen((message) {
// Handle real-time messages
add(ChatEvent.messagesRequested(message.chatId));
});
}
Future<void> _onStarted(ChatEventStarted event, Emitter<ChatState> emit) async {
// Start SignalR in background
chatRepository.initSignalR().catchError((e) {
// Log or handle SignalR init error
});
// Immediately trigger chats loading
add(const ChatEvent.chatsLoaded());
}
Future<void> _onChatsLoaded(ChatEventChatsLoaded event, Emitter<ChatState> emit) async {
emit(const ChatState.loading());
final result = await chatRepository.getChats(currentUserId: event.currentUserId);
result.fold(
(error) => emit(ChatState.error(error.message ?? 'Failed to load chats')),
(chats) => emit(ChatState.chatsLoaded(chats)),
);
}
Future<void> _onChatSelected(ChatEventChatSelected event, Emitter<ChatState> emit) async {
emit(const ChatState.loading());
final chatResult = await chatRepository.getChatById(event.chatId);
final messagesResult = await chatRepository.getMessages(event.chatId);
chatResult.fold(
(error) => emit(ChatState.error(error.message ?? 'Failed to load chat')),
(chat) {
messagesResult.fold(
(error) => emit(ChatState.chatSelected(chat, [])),
(messages) => emit(ChatState.chatSelected(chat, messages)),
);
},
);
}
Future<void> _onMessagesRequested(ChatEventMessagesRequested event, Emitter<ChatState> emit) async {
final result = await chatRepository.getMessages(event.chatId);
result.fold(
(error) => emit(ChatState.error(error.message ?? 'Failed to load messages')),
(messages) => emit(ChatState.messagesLoaded(messages)),
);
}
Future<void> _onMessageSent(ChatEventMessageSent event, Emitter<ChatState> emit) async {
final result = await chatRepository.sendMessage(event.chatId, event.content);
result.fold(
(error) => emit(ChatState.error(error.message ?? 'Failed to send message')),
(_) => add(ChatEvent.messagesRequested(event.chatId)),
);
}
Future<void> _onFavoritesRequested(ChatEventFavoritesRequested event, Emitter<ChatState> emit) async {
emit(const ChatState.loading());
final result = await chatRepository.getOrCreateFavorites();
result.fold(
(error) => emit(ChatState.error(error.message ?? 'Failed to open Favorites')),
(chat) => add(ChatEvent.chatSelected(chat.id)),
);
}
@override
Future<void> close() {
_messageSubscription?.cancel();
chatRepository.disposeSignalR();
return super.close();
}
}