You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			365 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			365 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Dart
		
	
| import 'dart:async';
 | |
| 
 | |
| import 'package:easy_localization/easy_localization.dart';
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter_svg/flutter_svg.dart';
 | |
| import 'package:mohem_flutter_app/api/chat/chat_provider_model.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/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/models/chat/call.dart';
 | |
| import 'package:mohem_flutter_app/ui/chat/call/chat_call_screen.dart';
 | |
| import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart';
 | |
| import 'package:mohem_flutter_app/widgets/app_bar_widget.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:swipe_to/swipe_to.dart';
 | |
| 
 | |
| class ChatDetailScreen extends StatefulWidget {
 | |
|   // ignore: prefer_const_constructors_in_immutables
 | |
|   ChatDetailScreen({Key? key}) : super(key: key);
 | |
| 
 | |
|   @override
 | |
|   State<ChatDetailScreen> createState() => _ChatDetailScreenState();
 | |
| }
 | |
| 
 | |
| class _ChatDetailScreenState extends State<ChatDetailScreen> {
 | |
|   dynamic userDetails;
 | |
|   late ChatProviderModel data;
 | |
|   final RefreshController _rc = RefreshController(initialRefresh: false);
 | |
| 
 | |
|   void getMoreChat() async {
 | |
|     if (userDetails != null) {
 | |
|       data.paginationVal = data.paginationVal + 10;
 | |
|       if (userDetails != null)
 | |
|         data.getSingleUserChatHistory(
 | |
|           senderUID: AppState().chatDetails!.response!.id.toString(),
 | |
|           receiverUID: userDetails["targetUser"].id,
 | |
|           loadMore: true,
 | |
|           isNewChat: false,
 | |
|         );
 | |
|     }
 | |
|     await Future.delayed(
 | |
|       const Duration(
 | |
|         milliseconds: 1000,
 | |
|       ),
 | |
|     );
 | |
|     _rc.loadComplete();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     userDetails = ModalRoute.of(context)!.settings.arguments;
 | |
|     data = Provider.of<ChatProviderModel>(context, listen: false);
 | |
|     if (userDetails != null)
 | |
|       data.getSingleUserChatHistory(
 | |
|         senderUID: AppState().chatDetails!.response!.id.toString(),
 | |
|         receiverUID: userDetails["targetUser"].id,
 | |
|         loadMore: false,
 | |
|         isNewChat: userDetails["isNewChat"],
 | |
|       );
 | |
|     return Scaffold(
 | |
|       backgroundColor: const Color(0xFFF8F8F8),
 | |
|       appBar: AppBarWidget(context,
 | |
|           title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach,
 | |
|           showHomeButton: false,
 | |
|           image: userDetails["targetUser"].image,
 | |
|           actions: [
 | |
|             IconButton(
 | |
|               onPressed: () {
 | |
|                 // makeCall("AUDIO");
 | |
|               },
 | |
|               icon: SvgPicture.asset(
 | |
|                 "assets/images/call.svg",
 | |
|                 width: 25,
 | |
|                 height: 25,
 | |
|               ),
 | |
|             ),
 | |
|             IconButton(
 | |
|               onPressed: () {
 | |
|                 //  makeCall("VIDEO");
 | |
|               },
 | |
|               icon: SvgPicture.asset(
 | |
|                 "assets/images/call.svg",
 | |
|                 width: 25,
 | |
|                 height: 25,
 | |
|               ),
 | |
|             ),
 | |
|           ]),
 | |
|       body: Consumer<ChatProviderModel>(
 | |
|         builder: (BuildContext context, ChatProviderModel m, Widget? child) {
 | |
|           return (m.isLoading
 | |
|               ? ChatHomeShimmer()
 | |
|               : Column(
 | |
|                   children: <Widget>[
 | |
|                     Expanded(
 | |
|                       flex: 2,
 | |
|                       child: SmartRefresher(
 | |
|                         enablePullDown: false,
 | |
|                         enablePullUp: true,
 | |
|                         onLoading: () {
 | |
|                           getMoreChat();
 | |
|                         },
 | |
|                         header: const MaterialClassicHeader(
 | |
|                           color: MyColors.gradiantEndColor,
 | |
|                         ),
 | |
|                         controller: _rc,
 | |
|                         reverse: true,
 | |
|                         child: ListView.builder(
 | |
|                           controller: m.scrollController,
 | |
|                           shrinkWrap: true,
 | |
|                           physics: const BouncingScrollPhysics(),
 | |
|                           reverse: true,
 | |
|                           itemCount: m.userChatHistory.length,
 | |
|                           padding: const EdgeInsets.only(top: 20),
 | |
|                           itemBuilder: (BuildContext context, int i) {
 | |
|                             return SwipeTo(
 | |
|                               iconColor: MyColors.lightGreenColor,
 | |
|                               child: ChatBubble(
 | |
|                                 text: m.userChatHistory[i].contant.toString(),
 | |
|                                 replyText: m.userChatHistory[i].userChatReplyResponse != null ? m.userChatHistory[i].userChatReplyResponse!.contant.toString() : "",
 | |
|                                 isSeen: m.userChatHistory[i].isSeen == true ? true : false,
 | |
|                                 isCurrentUser: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id ? true : false,
 | |
|                                 isDelivered: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id && m.userChatHistory[i].isDelivered == true ? true : false,
 | |
|                                 dateTime: m.dateFormte(m.userChatHistory[i].createdDate!),
 | |
|                                 isReplied: m.userChatHistory[i].userChatReplyResponse != null ? true : false,
 | |
|                                 userName: AppState().chatDetails!.response!.userName == m.userChatHistory[i].currentUserName.toString() ? "You" : m.userChatHistory[i].currentUserName.toString(),
 | |
|                               ),
 | |
|                               onRightSwipe: () {
 | |
|                                 m.chatReply(m.userChatHistory[i]);
 | |
|                               },
 | |
|                             );
 | |
|                           },
 | |
|                         ),
 | |
|                       ),
 | |
|                     ),
 | |
|                     if (m.isMsgReply)
 | |
|                       Row(
 | |
|                         children: <Widget>[
 | |
|                           Container(
 | |
|                             height: 80,
 | |
|                             color: MyColors.textMixColor,
 | |
|                             width: 6,
 | |
|                           ),
 | |
|                           Expanded(
 | |
|                             child: Container(
 | |
|                               height: 80,
 | |
|                               color: MyColors.black.withOpacity(0.10),
 | |
|                               child: ListTile(
 | |
|                                 title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString()
 | |
|                                         ? "You"
 | |
|                                         : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " "))
 | |
|                                     .toText14(color: MyColors.lightGreenColor),
 | |
|                                 subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2),
 | |
|                                 trailing: GestureDetector(
 | |
|                                   onTap: m.closeMe,
 | |
|                                   child: Container(
 | |
|                                     decoration: BoxDecoration(
 | |
|                                       color: MyColors.white.withOpacity(0.5),
 | |
|                                       borderRadius: const BorderRadius.all(
 | |
|                                         Radius.circular(20),
 | |
|                                       ),
 | |
|                                     ),
 | |
|                                     child: const Icon(
 | |
|                                       Icons.close,
 | |
|                                       size: 23,
 | |
|                                       color: MyColors.white,
 | |
|                                     ),
 | |
|                                   ),
 | |
|                                 ),
 | |
|                               ),
 | |
|                             ),
 | |
|                           ),
 | |
|                         ],
 | |
|                       ),
 | |
|                     if (m.isFileSelected && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg")
 | |
|                       Card(
 | |
|                         margin: EdgeInsets.zero,
 | |
|                         elevation: 0,
 | |
|                         child: Padding(
 | |
|                           padding: const EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 0),
 | |
|                           child: Card(
 | |
|                             margin: EdgeInsets.zero,
 | |
|                             shape: RoundedRectangleBorder(
 | |
|                               borderRadius: BorderRadius.circular(0),
 | |
|                             ),
 | |
|                             elevation: 0,
 | |
|                             child: Container(
 | |
|                               height: 200,
 | |
|                               decoration: BoxDecoration(
 | |
|                                 image: DecorationImage(
 | |
|                                   image: FileImage(
 | |
|                                     m.selectedFile,
 | |
|                                   ),
 | |
|                                   fit: BoxFit.cover,
 | |
|                                 ),
 | |
|                                 borderRadius: const BorderRadius.all(
 | |
|                                   Radius.circular(0),
 | |
|                                 ),
 | |
|                               ),
 | |
|                               child: const SizedBox(
 | |
|                                 width: double.infinity,
 | |
|                                 height: 200,
 | |
|                               ),
 | |
|                             ),
 | |
|                           ),
 | |
|                         ),
 | |
|                       ),
 | |
|                     Card(
 | |
|                       margin: EdgeInsets.zero,
 | |
|                       child: TextField(
 | |
|                         controller: m.message,
 | |
|                         decoration: InputDecoration(
 | |
|                           hintText: m.isFileSelected ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(),
 | |
|                           hintStyle: TextStyle(color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14),
 | |
|                           border: InputBorder.none,
 | |
|                           focusedBorder: InputBorder.none,
 | |
|                           enabledBorder: InputBorder.none,
 | |
|                           errorBorder: InputBorder.none,
 | |
|                           disabledBorder: InputBorder.none,
 | |
|                           contentPadding: EdgeInsets.only(left: m.sFileType.isNotEmpty ? 10 : 20, right: m.sFileType.isNotEmpty ? 0 : 5, top: 20, bottom: 20),
 | |
|                           prefixIcon: m.sFileType.isNotEmpty
 | |
|                               ? Row(
 | |
|                                   mainAxisSize: MainAxisSize.min,
 | |
|                                   mainAxisAlignment: MainAxisAlignment.start,
 | |
|                                   children: <Widget>[
 | |
|                                     SvgPicture.asset(
 | |
|                                       m.getType(m.sFileType),
 | |
|                                       height: 30,
 | |
|                                       width: 25,
 | |
|                                       alignment: Alignment.center,
 | |
|                                       fit: BoxFit.cover,
 | |
|                                     ).paddingOnly(left: 20),
 | |
|                                   ],
 | |
|                                 )
 | |
|                               : null,
 | |
|                           suffixIcon: SizedBox(
 | |
|                             width: 96,
 | |
|                             child: Row(
 | |
|                               mainAxisAlignment: MainAxisAlignment.end,
 | |
|                               crossAxisAlignment: CrossAxisAlignment.center, // added line
 | |
|                               children: <Widget>[
 | |
|                                 if (m.sFileType.isNotEmpty)
 | |
|                                   IconButton(
 | |
|                                     padding: EdgeInsets.zero,
 | |
|                                     alignment: Alignment.centerRight,
 | |
|                                     icon: Row(
 | |
|                                       crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                                       mainAxisAlignment: MainAxisAlignment.end,
 | |
|                                       mainAxisSize: MainAxisSize.max,
 | |
|                                       children: <Widget>[
 | |
|                                         Container(
 | |
|                                           decoration: const BoxDecoration(
 | |
|                                             color: MyColors.redA3Color,
 | |
|                                             borderRadius: BorderRadius.all(
 | |
|                                               Radius.circular(20),
 | |
|                                             ),
 | |
|                                           ),
 | |
|                                           child: const Icon(
 | |
|                                             Icons.close,
 | |
|                                             size: 15,
 | |
|                                             color: MyColors.white,
 | |
|                                           ),
 | |
|                                         ),
 | |
|                                         ("Clear").toText11(color: MyColors.redA3Color).paddingOnly(left: 4),
 | |
|                                       ],
 | |
|                                     ),
 | |
|                                     onPressed: () async {
 | |
|                                       m.removeAttachment();
 | |
|                                     },
 | |
|                                   ),
 | |
|                                 if (m.sFileType.isEmpty)
 | |
|                                   RotationTransition(
 | |
|                                     turns: const AlwaysStoppedAnimation(45 / 360),
 | |
|                                     child: IconButton(
 | |
|                                       padding: EdgeInsets.zero,
 | |
|                                       alignment: Alignment.topRight,
 | |
|                                       icon: const Icon(
 | |
|                                         Icons.attach_file_rounded,
 | |
|                                         size: 26,
 | |
|                                         color: MyColors.grey3AColor,
 | |
|                                       ),
 | |
|                                       onPressed: () async {
 | |
|                                         m.selectImageToUpload(context);
 | |
|                                       },
 | |
|                                     ),
 | |
|                                   ),
 | |
|                                 IconButton(
 | |
|                                   alignment: Alignment.centerRight,
 | |
|                                   padding: EdgeInsets.zero,
 | |
|                                   icon: SvgPicture.asset(
 | |
|                                     "assets/icons/chat/chat_send_icon.svg",
 | |
|                                     height: 26,
 | |
|                                     width: 26,
 | |
|                                   ),
 | |
|                                   onPressed: () {
 | |
|                                     m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName, context);
 | |
|                                   },
 | |
|                                 )
 | |
|                               ],
 | |
|                             ),
 | |
|                           ).paddingOnly(right: 20),
 | |
|                         ),
 | |
|                       ),
 | |
|                     ),
 | |
|                   ],
 | |
|                 ));
 | |
|         },
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   void makeCall(String callType) async {
 | |
|     // final server =  await SelectionDialog(
 | |
|     //     context,
 | |
|     //     title: "Select Server",
 | |
|     //     items: ["https://livecareturn.hmg.com:8086", "https://104.197.179.1:8086"]
 | |
|     // ).show();
 | |
| 
 | |
|     Map<String, String> json = {
 | |
|       "callerID": "9920",
 | |
|       "PatientID": "1231755",
 | |
|       "msgID": "123",
 | |
|       "notfID": "123",
 | |
|       "notification_foreground": "true",
 | |
|       "count": "1",
 | |
|       "message": "Doctor is calling ",
 | |
|       "AppointmentNo": "123",
 | |
|       "title": "Rayyan Hospital",
 | |
|       "ProjectID": "123",
 | |
|       "NotificationType": "10",
 | |
|       "background": "1",
 | |
|       "doctorname": "Dr Sulaiman Al Habib",
 | |
|       "clinicname": "ENT Clinic",
 | |
|       "speciality": "Speciality",
 | |
|       "appointmentdate": "Sun, 15th Dec, 2019",
 | |
|       "appointmenttime": "09:00",
 | |
|       "type": "video",
 | |
|       "session_id":
 | |
|           "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk",
 | |
|       "identity": "Haroon1",
 | |
|       "name": "SmallDailyStandup",
 | |
|       "videoUrl": "video",
 | |
|       "picture": "video",
 | |
|       "is_call": "true",
 | |
|       "is_webrtc": "true",
 | |
|       // "server": "https://192.168.8.163:8086",
 | |
|       "server": "https://livecareturn.hmg.com:8086",
 | |
|     };
 | |
| 
 | |
|     IncomingCallData incomingCallData = IncomingCallData.fromJson(json);
 | |
|     await Navigator.push(
 | |
|       context,
 | |
|       MaterialPageRoute(
 | |
|         builder: (BuildContext context) => IncomingCall(
 | |
|           incomingCallData: incomingCallData,
 | |
|           isVideoCall: callType == "VIDEO" ? true : false,
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |