feat(chat): add chat lazy loading, send message and websocket init for notifications and new chat messages

This commit is contained in:
alex
2024-07-05 22:28:03 +03:00
parent 7514a9b75f
commit 5f88f49c71
11 changed files with 216 additions and 113 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:io';
import 'package:dart_pusher_channels/dart_pusher_channels.dart';
import 'package:easy_debounce/easy_debounce.dart';
@@ -8,43 +9,47 @@ import 'package:eatvio_app/core/token_storage.dart';
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ChatRoomCubit extends Cubit<ChatRoomState> {
final ChatRepository chatRepository;
final InitializationCubit initializationCubit;
int currentPage = 1;
late final int lastPage;
bool isLoading = false;
late final PusherChannelsClient client;
late final PrivateChannel privateChannel;
late final PrivateChannel privateChatChannel;
ChatRoomCubit({
required this.chatRepository,
required this.initializationCubit,
}) : super(ChatRoomState.loading());
loadNextPage(String chatId) async {
if (currentPage < lastPage) {
if (currentPage < lastPage && !isLoading) {
isLoading = true;
emit(ChatRoomState.loaded(
chatRoom: (state as ChatRoomStateLoaded).chatRoom,
chatMessages: (state as ChatRoomStateLoaded).chatMessages,
isTyping: (state as ChatRoomStateLoaded).isTyping,
isLoading: true,
isLoading: isLoading,
));
try {
final chatMessages = await chatRepository.getChatMessages(chatId, currentPage + 1);
isLoading = false;
emit(ChatRoomState.loaded(
chatRoom: (state as ChatRoomStateLoaded).chatRoom,
chatMessages: [...(state as ChatRoomStateLoaded).chatMessages, ...chatMessages.messagesList],
isTyping: (state as ChatRoomStateLoaded).isTyping,
isLoading: false,
isLoading: isLoading,
));
currentPage++;
} catch (e) {
print(e);
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
@@ -59,20 +64,13 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
final chatMessages = await chatRepository.getChatMessages(chatId, currentPage);
lastPage = chatMessages.meta.lastPage;
final initCubit = sl<InitializationCubit>();
if (initCubit.state is InitializationStateSuccess) {
await subscribeToChatChannel(initCubit: initCubit, chatId: chatId);
} else {
await initCubit.runInitialization();
await subscribeToChatChannel(initCubit: initCubit, chatId: chatId);
}
await subscribeToChatChannel(initCubit: initializationCubit, chatId: chatId);
emit(ChatRoomState.loaded(
chatRoom: chatRoom,
chatMessages: chatMessages.messagesList,
isTyping: false,
isLoading: false,
isLoading: isLoading,
));
} catch (e) {
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
@@ -85,7 +83,7 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
}) async {
client = (initCubit.state as InitializationStateSuccess).client;
privateChannel = await client.privateChannel(
privateChatChannel = await client.privateChannel(
'private-direct-chat.$chatId',
authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate.forPrivateChannel(
authorizationEndpoint: Uri.parse('https://mobile-stage.eatvio.ru/broadcasting/auth'),
@@ -95,9 +93,9 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
),
);
privateChannel.subscribe();
privateChatChannel.subscribe();
privateChannel.bind('App\\Events\\ChatMessageUpdated').listen((event) {
privateChatChannel.bind('App\\Events\\ChatMessageUpdated').listen((event) {
List<ChatMessageModel> messagesList = [
ChatMessageModel.fromJson(jsonDecode(event.data)['message']),
...(state as ChatRoomStateLoaded).chatMessages,
@@ -107,18 +105,18 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
chatRoom: (state as ChatRoomStateLoaded).chatRoom,
chatMessages: messagesList,
isTyping: (state as ChatRoomStateLoaded).isTyping,
isLoading: false,
isLoading: isLoading,
),
);
});
privateChannel.bind('client-typing').listen((event) {
privateChatChannel.bind('client-typing').listen((event) {
emit(
ChatRoomState.loaded(
chatRoom: (state as ChatRoomStateLoaded).chatRoom,
chatMessages: (state as ChatRoomStateLoaded).chatMessages,
isTyping: true,
isLoading: false,
isLoading: isLoading,
),
);
EasyDebounce.debounce(
@@ -129,16 +127,24 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
chatRoom: (state as ChatRoomStateLoaded).chatRoom,
chatMessages: (state as ChatRoomStateLoaded).chatMessages,
isTyping: false,
isLoading: false,
isLoading: isLoading,
),
),
);
});
}
sendMessage({
required String chatId,
required String data,
required List<File> filesList,
}) async {
await chatRepository.sendMessage(chatId: chatId, data: data);
}
@override
Future<void> close() async {
privateChannel.unsubscribe();
privateChatChannel.unsubscribe();
super.close();
}
}