import 'package:flutter/material.dart'; import 'package:ftc_mobile_app/ftc_mobile_app.dart'; import 'package:ftc_mobile_app/models/chat/ChatModel.dart'; import 'package:ftc_mobile_app/utilities/extensions/custom_extensions.dart'; import 'package:ftc_mobile_app/view/custom_widgets/my_circle_image.dart'; import 'package:get/get.dart'; import 'package:grouped_list/grouped_list.dart'; import 'package:intl/intl.dart'; import 'arguments/chat_screen_args.dart'; import 'widgets/chat_screen_footer_widget.dart'; import 'widgets/message_bubble.dart'; class ChatScreen extends StatefulWidget { final ChatScreenArgs args; const ChatScreen({Key? key, required this.args}) : super(key: key); @override State createState() => _ChatScreenState(); } class _ChatScreenState extends State { late final ChatScreenController controller; final sepFormatter = DateFormat("dd MMM yyyy"); @override void initState() { controller = Get.put(ChatScreenController(widget.args)); super.initState(); } @override Widget build(BuildContext context) { return CustomScaffold( backgroundColor: Colors.white, screenKey: controller.screenKey, onScreenTap: controller.removeFocus, showAppBar: true, appBar: _appBar, body: SafeArea( child: Column( children: [ Expanded(child: messagesList()), Obx(() { return controller.isSocketConnected() ? ChatScreenFooterWidget( controller: controller, enabled: controller.isSocketConnected(), ) : FrequentFunctions.noWidget; }) ], ), ), ); } AppBar get _appBar { return AppBar( toolbarHeight: 56.r, leading: IconButton( icon: CustomImageWidget( imagePath: AssetsManager.kBackIcon, height: 11.53.h, width: 8.66.w, ), onPressed: () { Navigator.pop(context); }, ), centerTitle: false, titleSpacing: 0, leadingWidth: 50.r, surfaceTintColor: Colors.white, title: Row( mainAxisSize: MainAxisSize.min, children: [ MyCircleImage( imageSize: 32.r, url: "${WebUrls.baseUrl}${widget.args.profilePicPath}", errorWidget: CustomImageWidget( imagePath: AssetsManager.kPersonMainIcon, imageColor: CustomAppColors.kDarkBlueTextColor, height: 32.r, width: 32.r, ), ), 10.horizontalSpace, CustomTextWidget( text: widget.args.name, isExpanded: false, fontSize: 16.sp, fontWeight: FontWeight.w700, fontColor: CustomAppColors.kDarkBlueTextColor, ), ], ), ); } Widget messagesList() { return Obx(() { final messages = controller.messages; return (messages.isEmpty) ? FrequentFunctions.noWidget : _messagesList(messages()); }); } Widget _messagesList(List list) { final now = DateTime.now(); return GroupedListView( reverse: true, elements: list, padding: REdgeInsets.symmetric(horizontal: 18), order: GroupedListOrder.DESC, groupBy: (message) { final messageDate = DateTime.fromMillisecondsSinceEpoch(message.date ?? 0); return DateFormatter.dateFormatter.format(messageDate); }, groupSeparatorBuilder: (String date) { final isToday = (date == DateFormatter.dateFormatter.format(now)); return _buildGroupSeparatorWidget(isToday ? "Today" : sepFormatter.format(DateFormatter.dateFormatter.parse(date))); }, itemBuilder: (_, e) => _buildItemWidget(list.indexOf(e), e), sort: false, separator: 8.verticalSpace, ); } Widget _buildGroupSeparatorWidget(String susTag) { return Padding( padding: REdgeInsets.symmetric(vertical: 12.0), child: Row( children: [ Expanded( child: Divider( height: 1, color: Colors.grey.withOpacity(0.3), )), Text( susTag, style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500), ).addPaddingHorizontal(10), Expanded( child: Divider( height: 1, color: Colors.grey.withOpacity(0.3), )), ], ), ); } Widget _buildItemWidget(int index, ChatModel message) { final isMyMessage = (message.from?.id == controller.myId); final hasFile = message.filePath.isNotNullOrEmpty(); print("filePath: ${message.filePath}"); return MessageBubble( senderName: message.from?.name ?? "", profilePic: !isMyMessage ? (message.from?.profilePictureUrl ?? "") : "", content: hasFile ? (message.filePath ?? '') : (message.message ?? ''), type: isMyMessage ? MessageType.sent : MessageType.received, contentType: hasFile ? (message.fileType == ChatModel.fileTypeLocalPath) ? MessageContentType.file : MessageContentType.url : MessageContentType.text, sentMessageColor: CustomAppColors.kSmokeColor, receivedMessageColor: CustomAppColors.kSecondaryColor, messageTime: (message.date == null) ? "" : DateTime.fromMillisecondsSinceEpoch(message.date!) .toIso8601String(), state: MessageState.stateNone, status: MessageSeenStatus.seen, ); } @override void dispose() { controller.dispose(); super.dispose(); } }