import 'dart:async'; import 'package:audio_waveforms/audio_waveforms.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/ui/chat/common.dart'; import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; import 'package:swipe_to/swipe_to.dart'; class ChatDetailedScreenParams { ChatUser? chatUser; bool? isNewChat; ChatDetailedScreenParams(this.chatUser, this.isNewChat); } class ChatDetailScreen extends StatefulWidget { const ChatDetailScreen({Key? key}) : super(key: key); @override State createState() => _ChatDetailScreenState(); } class _ChatDetailScreenState extends State { final RefreshController _rc = RefreshController(initialRefresh: false); late ChatProviderModel data; ChatDetailedScreenParams? params; var textDirection = TextDirection.RTL; void getMoreChat() async { if (params != null) { data.paginationVal = data.paginationVal + 10; if (params != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), receiverUID: params!.chatUser!.id!, loadMore: true, isNewChat: false, ); } } await Future.delayed( const Duration(milliseconds: 1000), ); _rc.loadComplete(); } @override void dispose() { data.disposeAudio(); super.dispose(); } @override Widget build(BuildContext context) { params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams; data = Provider.of(context, listen: false); if (params != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), receiverUID: params!.chatUser!.id!, loadMore: false, isNewChat: params!.isNewChat!, ); data.initAudio(receiverId: params!.chatUser!.id!); } return Scaffold( backgroundColor: MyColors.backgroundColor, appBar: ChatAppBarWidget( context, title: params!.chatUser!.userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, showTyping: true, chatUser: params!.chatUser, actions: [ // SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { // // makeCall(callType: "AUDIO", con: hubConnection); // }), // 24.width, // SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() { // // makeCall(callType: "VIDEO", con: hubConnection); // }), // 21.width, ], ), body: SafeArea( child: Consumer( builder: (BuildContext context, ChatProviderModel m, Widget? child) { return (m.isLoading ? ChatHomeShimmer( isDetailedScreen: true, ) : Column( children: [ SmartRefresher( enablePullDown: false, enablePullUp: true, onLoading: () { getMoreChat(); }, header: const MaterialClassicHeader( color: MyColors.gradiantEndColor, ), controller: _rc, reverse: true, child: ListView.separated( controller: m.scrollController, shrinkWrap: true, physics: const BouncingScrollPhysics(), reverse: true, itemCount: m.userChatHistory.length, padding: const EdgeInsets.all(21), separatorBuilder: (BuildContext cxt, int index) => 8.height, itemBuilder: (BuildContext context, int i) { return SwipeTo( iconColor: MyColors.lightGreenColor, child: ChatBubble( dateTime: m.dateFormte(m.userChatHistory[i].createdDate!), cItem: m.userChatHistory[i], ), onRightSwipe: () { m.chatReply( m.userChatHistory[i], ); }, ).onPress(() async { logger.w(m.userChatHistory[i].toJson()); if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) { if (m.userChatHistory[i].fileTypeId! == 1 || m.userChatHistory[i].fileTypeId! == 5 || m.userChatHistory[i].fileTypeId! == 7 || m.userChatHistory[i].fileTypeId! == 6 || m.userChatHistory[i].fileTypeId! == 8 // || m.userChatHistory[i].fileTypeId! == 2 ) { m.getChatMedia(context, fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); } } }); }, ), ).expanded, if (m.isReplyMsg) SizedBox( height: 82, child: Row( children: [ Container(height: 82, color: MyColors.textMixColor, width: 6), Container( color: MyColors.darkTextColor.withOpacity(0.10), padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() ? "You" : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) .toText14(color: MyColors.lightGreenColor), (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) ], ).expanded, 12.width, if (m.isReplyMsg && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m), 12.width, const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), ], ), ).expanded, ], ), ), if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), const Divider(height: 1, color: MyColors.lightGreyEFColor), if (m.isRecoding) Column( children: [ Row( children: [ Text(m.buildTimer()).paddingAll(10), if (m.isRecoding && m.isPlaying) WaveBubble( playerController: m.playerController, isPlaying: m.playerController.playerState == PlayerState.playing, onTap: () {}, ).expanded else AudioWaveforms( waveStyle: const WaveStyle( waveColor: MyColors.lightGreenColor, middleLineColor: Colors.transparent, extendWaveform: true, showBottom: true, showTop: true, waveThickness: 2, showMiddleLine: false, middleLineThickness: 0, ), padding: const EdgeInsets.all(5), shouldCalculateScrolledPosition: false, margin: EdgeInsets.zero, size: const Size(double.infinity, 30.0), recorderController: m.recorderController, backgroundColor: Colors.white, ).expanded, ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Icon( Icons.delete_outlined, size: 26, color: MyColors.lightGreenColor, ).paddingAll(10).onPress(() { m.deleteRecoding(); }), SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) .onPress( () => m.sendChatMessage(context, targetUserId: params!.chatUser!.id!, userStatus: params!.chatUser!.userStatus ?? 0, userEmail: params!.chatUser!.email!, targetUserName: params!.chatUser!.userName!), ) .paddingOnly(right: 21), ], ), ], ).objectContainerView(disablePadding: true, radius: 0), if (!m.isRecoding) Row( children: [ TextField( textDirection: m.textDirection, controller: m.message, decoration: InputDecoration( hintTextDirection: m.textDirection, hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : m.textDirection.name == "rtl" ? "اكتب هنا للرد" :LocaleKeys.typeheretoreply.tr(), hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), border: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, errorBorder: InputBorder.none, disabledBorder: InputBorder.none, filled: true, fillColor: MyColors.white, contentPadding: const EdgeInsets.only( left: 21, top: 20, bottom: 20, ), prefixIconConstraints: const BoxConstraints(), prefixIcon: m.sFileType.isNotEmpty ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) : null, ), onChanged: (String val) { m.inputBoxDirection(val); m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!); }, ).expanded, if (m.sFileType.isNotEmpty) Row( children: [ const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), ], ).onPress(() => m.removeAttachment()).paddingOnly(right: 15), if (m.sFileType.isEmpty) RotationTransition( turns: const AlwaysStoppedAnimation(45 / 360), child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( () => m.selectImageToUpload(context), ), ).paddingOnly(right: 15), const Icon( Icons.mic, color: MyColors.lightGreenColor, ).paddingOnly(right: 15).onPress(() { m.startRecoding(context); }), SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) .onPress( () => m.sendChatMessage(context, targetUserId: params!.chatUser!.id!, userStatus: params!.chatUser!.userStatus ?? 0, userEmail: params!.chatUser!.email!, targetUserName: params!.chatUser!.userName!), ) .paddingOnly(right: 21), ], ).objectContainerView(disablePadding: true, radius: 0), ], )); }, ), ), ); } Widget showReplyImage(List data, ChatProviderModel m) { if (data.first.isImageLoaded! && data.first.image != null) { return Container( width: 43, height: 43, decoration: BoxDecoration( border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)), ); } else { return data.first.fileTypeResponse != null && data.first.fileTypeResponse!.fileTypeName != null ? Container( width: 43, height: 43, constraints: const BoxConstraints(), decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white), child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName ?? ""), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) : const SizedBox(); } } void makeCall({required String callType, required HubConnection con}) async { print("================== Make call Triggered ============================"); Map json = { "callerID": AppState().chatDetails!.response!.id!.toString(), "callReceiverID": params!.chatUser!.id.toString(), "notification_foreground": "true", "message": "Aamir is calling", "title": "Video Call", "type": callType == "VIDEO" ? "Video" : "Audio", "identity": AppState().chatDetails!.response!.userName, "name": AppState().chatDetails!.response!.title, "is_call": "true", "is_webrtc": "true", "contant": "Start video Call ${AppState().chatDetails!.response!.userName}", "contantNo": "775d1f11-62d9-6fcc-91f6-21f8c14559fb", "chatEventId": "3", "fileTypeId": null, "currentUserId": AppState().chatDetails!.response!.id!.toString(), "chatSource": "1", "userChatHistoryLineRequestList": [ { "isSeen": false, "isDelivered": false, "targetUserId": params!.chatUser!.id!, "targetUserStatus": 4, } ], // "server": "https://192.168.8.163:8086", "server": "https://livecareturn.hmg.com:8086", }; CallDataModel callData = CallDataModel.fromJson(json); await Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => OutGoingCall( isVideoCall: callType == "VIDEO" ? true : false, OutGoingCallData: callData, ), ), ); } }