import 'dart:developer'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:get/get.dart'; import 'package:lottie/lottie.dart'; import 'package:taafee_mobile/common/const/const.dart'; import 'package:taafee_mobile/common/extensions/widget_extension.dart'; import 'package:taafee_mobile/common/widgets/loader.dart'; import 'package:taafee_mobile/common/widgets/text.dart'; import 'package:taafee_mobile/features/chat/business%20logic%20layer/chat_controller.dart'; import 'package:taafee_mobile/features/chat/data_layer/model/message.dart'; import 'package:taafee_mobile/features/chat/presentation_layer/widgets/appbar.dart'; import 'package:taafee_mobile/features/chat/presentation_layer/widgets/chat_date_divider.dart'; import 'package:taafee_mobile/features/chat/presentation_layer/widgets/chat_footer.dart'; import '../../../../common/widgets/toast.dart'; import '../../data_layer/model/room.dart'; import '../widgets/message_widget.dart'; class ChatDetails extends StatelessWidget { ChatDetails({super.key}); final FocusNode textFieldFocusNode = FocusNode(); final ChatController chatController = Get.find(); final KeyboardVisibilityController _keyboardVisibilityController = KeyboardVisibilityController(); Room room = Get.arguments; void loadMessages() { if (chatController.currentRoom.value!.messages.page < 2) { chatController.getCurrentRoomMessages(); } } void loadMoreMessages() { chatController.scrollController.value.addListener(() { if (chatController.scrollController.value.offset > ((chatController.currentRoom.value!.messages.length - 2) * 40)) { chatController.getCurrentRoomMessages(); } }); } void handleKeyBoardChanges() { _keyboardVisibilityController.onChange.listen((bool visible) { chatController.setkeyBoardOpened(visible); if (visible) { // Keyboard is opened log('Keyboard opened!'); } else { // Keyboard is closed log('Keyboard closed!'); } }); } void checkTablet() { if (Responsive.isTablet()) { Future.delayed(Duration(seconds: 2), () { chatController.getCurrentRoomMessages(); }); } } @override Widget build(BuildContext context) { loadMessages(); loadMoreMessages(); checkTablet(); handleKeyBoardChanges(); return WillPopScope( onWillPop: () async { if (room.type == RoomType.private) { chatController.updateRoom(); } return true; }, child: Scaffold( backgroundColor: AppColors.backGroundColor, body: Stack( children: [ Column( children: [ AppBarChatWidget( chatUser: room.user, roomType: room.type, avatar: room.user?.avatar, ), Expanded( child: SingleChildScrollView( physics: NeverScrollableScrollPhysics(), child: Column( mainAxisSize: MainAxisSize.min, children: [ Obx(() { return SizedBox( height: (chatController.keyBoardOpened.value) ? (Responsive.isTablet()) ? Get.height * 0.6 : Get.height * 0.5 : (Responsive.isTablet()) ? Get.height * 0.9 : Get.height * 0.8, child: Obx(() { if (chatController.currentRoom.value!.messages .data.isEmpty && chatController.messagesState.anyLoading) { return Loader().center(); } return Obx(() { return ListView.separated( separatorBuilder: ((context, index) { if (index == chatController.currentRoom.value! .messages.data.length - 1) { return ChatDateDivider( dateTime: chatController .currentRoom .value! .messages .data[index] .createdAt .toString() .substring(0, 10)); } if (index <= chatController.currentRoom.value! .messages.data.length - 1 && chatController .currentRoom .value! .messages .data[index] .createdAt .toString() .substring(0, 10) != chatController .currentRoom .value! .messages .data[index + 1] .createdAt .toString() .substring(0, 10)) { return ChatDateDivider( dateTime: chatController .currentRoom .value! .messages .data[index] .createdAt .toString() .substring(0, 10)); } return Container(); }), dragStartBehavior: DragStartBehavior.down, controller: chatController.scrollController.value, reverse: true, physics: const BouncingScrollPhysics(), itemCount: chatController.currentRoom.value! .messages.data.length + 1, itemBuilder: (context, index) { if (index > chatController.currentRoom.value! .messages.data.length - 1) { return Container(); } if (index == 0) { return Obx(() { return MessageWidget( messageModel: chatController .currentRoom .value! .messages .data[index], textFieldFocusNode: textFieldFocusNode, ).paddingOnly( right: (Responsive.isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection .received) ? Get.width * 0.5 : 0, left: (Responsive.isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection.sent) ? Get.width * 0.5 : 0, bottom: (chatController .keyBoardOpened.value) ? 100 : 50, ); }); } if (index == chatController.currentRoom.value! .messages.data.length - 1) { if (chatController .messagesState.anyLoading) { return Column( children: [ Loader(), Obx(() { return MessageWidget( messageModel: chatController .currentRoom .value! .messages .data[index], textFieldFocusNode: textFieldFocusNode, ).paddingOnly( right: (Responsive .isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection .received) ? Get.width * 0.5 : 0, left: (Responsive .isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection .sent) ? Get.width * 0.5 : 0, top: 16, ); }), ], ); } if (index == chatController.currentRoom.value! .messages.data.length) { return Container(); } return Obx(() { return MessageWidget( messageModel: chatController .currentRoom .value! .messages .data[index], textFieldFocusNode: textFieldFocusNode, ).paddingOnly( right: (Responsive.isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection .received) ? Get.width * 0.5 : 0, left: (Responsive.isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection.sent) ? Get.width * 0.5 : 0, top: 16, ); }); } return Obx(() { return MessageWidget( messageModel: chatController .currentRoom .value! .messages .data[index], textFieldFocusNode: textFieldFocusNode, ).paddingOnly( right: (Responsive.isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection.received) ? Get.width * 0.5 : 0, left: (Responsive.isTablet() && chatController .currentRoom .value! .messages .data[index] .direction == MessageDirection.sent) ? Get.width * 0.5 : 0, ); }); }); }); }), ).paddingSymmetric(horizontal: 12); }), ], ), ), ), Obx(() { return Visibility( visible: (chatController.currentRoom.value!.state == RoomState.active), child: ChatFooterWidget( focusNode: textFieldFocusNode, ), ); }), Obx(() { return Visibility( visible: (chatController.currentRoom.value!.state != RoomState.active), child: Material( borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), elevation: 15, child: Container( width: Get.width, decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), ), child: Column( children: [ RegularTextWidget( (room.state == RoomState.blocked) ? 'you_have_blocked_this_user'.tr : 'this_user_has_blocked_you'.tr, fontSize: 15, ), Visibility( visible: (room.state == RoomState.blocked), child: TextButton( onPressed: () { if (chatController.connectionState.value == SocketConnectionState.connected) { chatController.unblockRoom(); } else { Toast.showToast( 'you_have_no_internet_connection'.tr); } }, child: Text('unblock'.tr), )), ], ).paddingOnly(top: 12, bottom: 16), ), ), ); }) ], ).makeSafeArea(), Obx(() { return Visibility( visible: (chatController.connectionState.value != SocketConnectionState.connected) && chatController .currentRoom.value!.messages.data.isNotEmpty, child: SizedBox( width: 160, height: 160, child: Lottie.asset( 'assets/animations/Wifi Lottie.json'))) .align(alignment: Alignment.center); }), ], ), ), ); } }