From 0538a3c313f006697483f1a1feb7063e41a8b00f Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 28 Nov 2022 15:59:15 +0300 Subject: [PATCH] Chat Fixes & Chat Media Preview Api Implementation --- lib/api/chat/chat_api_client.dart | 83 ++++++++++++++++++---- lib/api/dashboard_api_client.dart | 28 ++++---- lib/classes/consts.dart | 5 +- lib/provider/chat_provider_model.dart | 16 +++++ lib/provider/dashboard_provider_model.dart | 2 - lib/ui/chat/chat_bubble.dart | 38 +++++++++- lib/ui/chat/chat_detailed_screen.dart | 35 +++++---- lib/ui/chat/chat_home_screen.dart | 12 +++- lib/ui/chat/favorite_users_screen.dart | 12 +++- 9 files changed, 178 insertions(+), 53 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 6355417..91b622a 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:typed_data'; import 'package:http/http.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; @@ -46,13 +47,30 @@ class ChatApiClient { ); Future getRecentChats() async { - Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatRecentUrl}getchathistorybyuserid", - token: AppState().chatDetails!.response!.token, - ); - return ChatUserModel.fromJson( - json.decode(response.body), - ); + try { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatRecentUrl}getchathistorybyuserid", + token: AppState().chatDetails!.response!.token, + ); + return ChatUserModel.fromJson( + json.decode(response.body), + ); + } catch (e) { + e as APIException; + if (e.message == "api_common_unauthorized") { + logger.d("Token Generated On APIIIIII"); + user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + if (userLoginResponse.response != null) { + AppState().setchatUserDetails = userLoginResponse; + getRecentChats(); + } else { + Utils.showToast( + userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + ); + } + } + throw e; + } } Future getFavUsers() async { @@ -66,11 +84,27 @@ class ChatApiClient { } Future getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async { - Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal", - token: AppState().chatDetails!.response!.token, - ); - return response; + try { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal", + token: AppState().chatDetails!.response!.token, + ); + return response; + } catch (e) { + e as APIException; + if (e.message == "api_common_unauthorized") { + user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + if (userLoginResponse.response != null) { + AppState().setchatUserDetails = userLoginResponse; + getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); + } else { + Utils.showToast( + userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + ); + } + } + throw e; + } } Future favUser({required int userID, required int targetUserID}) async { @@ -120,4 +154,29 @@ class ChatApiClient { StreamedResponse response = await request.send(); return response; } + + // Download File For Chat + + Future downloadURL({required String fileName, required String fileTypeDescription}) async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatMediaImageUploadUrl}download", + {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": 1}, + token: AppState().chatDetails!.response!.token, + ); + Uint8List data = Uint8List.fromList(response.bodyBytes); + return data; + } + + Future getUsersImages({required List encryptedEmails}) async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatUserImages}images", + { + "encryptedEmails": ["/g8Rc+s6eEOdci41PwJuV5dX+gXe51G9OTHzb9ahcVlHCmVvNhxReirudF79+hdxVSkCnQ6wC5DBFV8xnJlC74X6157PxF7mNYrAYuHRgp4="], + "fromClient": true + }, + token: AppState().chatDetails!.response!.token, + ); + logger.d(response.body); + // Uint8List data = Uint8List.fromList(response.body); + } } diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 69c2e82..e30af91 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -182,22 +182,22 @@ class DashboardApiClient { Future getChatCount() async { Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}user/unreadconversationcount/${AppState().getUserName}", + "${ApiConsts.chatLoginTokenUrl}unreadconversationcount/${AppState().getUserName}", ); return chatUnreadCovnCountModelFromJson(response.body); } - // Future setAdvertisementViewed(String masterID, int advertisementId) async { - // String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed"; - // - // Map postParams = { - // "ItgNotificationMasterId": masterID, - // "ItgAdvertisement": {"advertisementId": advertisementId, "acknowledgment": true} //Mobile Id - // }; - // postParams.addAll(AppState().postParamsJson); - // return await ApiClient().postJsonForObject((json) { - // // ItgMainRes responseData = ItgMainRes.fromJson(json); - // return json; - // }, url, postParams); - // } +// Future setAdvertisementViewed(String masterID, int advertisementId) async { +// String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed"; +// +// Map postParams = { +// "ItgNotificationMasterId": masterID, +// "ItgAdvertisement": {"advertisementId": advertisementId, "acknowledgment": true} //Mobile Id +// }; +// postParams.addAll(AppState().postParamsJson); +// return await ApiClient().postJsonForObject((json) { +// // ItgMainRes responseData = ItgMainRes.fromJson(json); +// return json; +// }, url, postParams); +// } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index edc866f..4e9c9b6 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,6 +1,6 @@ class ApiConsts { - // static String baseUrl = "http://10.200.204.20:2801/"; // Local server - //static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + // static String baseUrl = "http://10.200.204.20:2801/"; // Local server + //static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server @@ -23,6 +23,7 @@ class ApiConsts { static String chatSingleUserHistoryUrl = chatServerBaseApiUrl + "UserChatHistory/"; static String chatMediaImageUploadUrl = chatServerBaseApiUrl + "shared/"; static String chatFavUser = chatServerBaseApiUrl + "FavUser/"; + static String chatUserImages = chatServerBaseUrl + "empservice/api/employee/"; } class SharedPrefsConsts { diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 655de86..e08562e 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -283,6 +283,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future onMsgReceived(List? parameters) async { + print("--------------------------------RMSG-----------------------------"); + logger.d(parameters); List data = []; List temp = []; for (dynamic msg in parameters!) { @@ -652,6 +654,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); } + // Future getDownLoadFile(String fileName) async { + // var data = await ChatApiClient().downloadURL(fileName: "data"); + // Image.memory(data); + // } + // void getUserChatHistoryNotDeliveredAsync({required int userId}) async { // try { // await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); @@ -659,4 +666,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // hubConnection.off("GetUserChatHistoryNotDeliveredAsync", method: chatNotDelivered); // } // } + + + + + + + + + } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index b785293..59b62b6 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -295,7 +295,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future getUserAutoLoginToken() async { - logger.d("Token Generated On Home"); UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); if (userLoginResponse.response != null) { AppState().setchatUserDetails = userLoginResponse; @@ -315,7 +314,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isChatHubLoding = false; return hub; } - void notify() { notifyListeners(); } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index bcf78aa..8382585 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -1,8 +1,13 @@ +import 'dart:typed_data'; + import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/api_client.dart'; +import 'package:mohem_flutter_app/api/chat/chat_api_client.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/main.dart'; // todo: @aamir use extension methods, and use correct widgets. @@ -16,7 +21,9 @@ class ChatBubble extends StatelessWidget { required this.isDelivered, required this.dateTime, required this.isReplied, - required this.userName}) + required this.userName, + this.fileTypeID, + this.fileTypeDescription}) : super(key: key); final String text; final String replyText; @@ -26,6 +33,8 @@ class ChatBubble extends StatelessWidget { final String dateTime; final bool isReplied; final String userName; + final int? fileTypeID; + final String? fileTypeDescription; @override Widget build(BuildContext context) { @@ -177,7 +186,8 @@ class ChatBubble extends StatelessWidget { ).expanded, ), ).paddingOnly(right: 5, bottom: 7), - (text).toText12(), + if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3) showImage().paddingOnly(right: 5), + if (fileTypeID != 12 || fileTypeID != 4 || fileTypeID != 3) (text).toText12(), Align( alignment: Alignment.centerRight, child: Row( @@ -237,7 +247,7 @@ class ChatBubble extends StatelessWidget { ).expanded, ), ).paddingOnly(right: 5, bottom: 7), - (text).toText12(color: Colors.white), + if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3) showImage().paddingOnly(right: 5) else (text).toText12(color: Colors.white), Align( alignment: Alignment.centerRight, child: dateTime.toText10( @@ -248,4 +258,26 @@ class ChatBubble extends StatelessWidget { ), ).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); } + + Widget showImage() { + return FutureBuilder( + future: ChatApiClient().downloadURL(fileName: text, fileTypeDescription: fileTypeDescription!), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState != ConnectionState.waiting) { + if (snapshot.data == null) { + return (text).toText12(color: Colors.white); + } else { + return Image.memory( + snapshot.data, + height: 140, + width: 227, + fit: BoxFit.cover, + ); + } + } else { + return const SizedBox(height: 140, width: 227, child: Center(child: CircularProgressIndicator())); + } + }, + ); + } } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index e0f7f93..4dc7c35 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -9,6 +10,7 @@ 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/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart'; @@ -74,21 +76,14 @@ class _ChatDetailScreenState extends State { showHomeButton: false, image: userDetails["targetUser"].image, actions: [ - IconButton( - constraints: const BoxConstraints(), - onPressed: () { - // makeCall(callType: "AUDIO", con: hubConnection); - }, - icon: SvgPicture.asset("assets/icons/chat/call.svg", width: 22, height: 22), - ), - IconButton( - constraints: const BoxConstraints(), - onPressed: () { - //makeCall(callType: "VIDEO", con: hubConnection); - }, - icon: SvgPicture.asset("assets/icons/chat/video_call.svg", width: 20, height: 20), - ), - 10.width, + 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: Consumer( @@ -128,13 +123,17 @@ class _ChatDetailScreenState extends State { 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(), + fileTypeID: m.userChatHistory[i].fileTypeId, + fileTypeDescription: m.userChatHistory[i].fileTypeResponse!.fileTypeDescription, ), onRightSwipe: () { m.chatReply( m.userChatHistory[i], ); }, - ); + ).onPress(() { + logger.d(jsonEncode(m.userChatHistory[i])); + }); }, ), ).expanded, @@ -181,12 +180,12 @@ class _ChatDetailScreenState extends State { disabledBorder: InputBorder.none, filled: true, fillColor: MyColors.white, - contentPadding: EdgeInsets.only( + contentPadding: const EdgeInsets.only( left: 21, top: 20, bottom: 20, ), - prefixIconConstraints: BoxConstraints(), + 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, diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index cf6b8d2..9072b33 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -169,7 +169,17 @@ class _ChatHomeScreenState extends State { ), ], ), - ); + ).onPress(() { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.searchedChats![index], "isNewChat": false}, + ).then((Object? value) { + // m.GetUserChatHistoryNotDeliveredAsync(userId: int.parse(AppState().chatDetails!.response!.id.toString())); + m.clearSelections(); + m.notifyListeners(); + }); + }); }, separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.lightGreyE5Color).paddingOnly(left: 59), ).paddingOnly(bottom: 70).expanded, diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 88c8f9a..6bc0040 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -87,7 +87,17 @@ class ChatFavoriteUsersScreen extends StatelessWidget { ), ], ), - ); + ).onPress(() { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.favUsersList![index], "isNewChat": false}, + ).then( + (Object? value) { + m.clearSelections(); + }, + ); + }); }, separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.lightGreyE5Color).paddingOnly(left: 70), ).paddingAll(21)