93 lines
3.4 KiB
Dart
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();
|
|
}
|
|
}
|