From 00dee97bca969b495a5568fcbc96022f287f2904 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Wed, 16 Nov 2022 16:44:46 +0300 Subject: [PATCH] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/api/chat/chat_provider_model.dart | 42 +++++++--- lib/api/dashboard_api_client.dart | 10 ++- lib/classes/consts.dart | 4 +- .../chat/chat_count_conversation_model.dart | 25 ++++++ .../chat/get_user_login_token_model.dart | 81 ++++++++++++------- lib/provider/dashboard_provider_model.dart | 22 ++++- lib/ui/chat/call/chat_call_screen.dart | 2 + lib/ui/chat/chat_detailed_screen.dart | 28 ++++--- lib/ui/chat/chat_home.dart | 9 ++- lib/ui/landing/dashboard_screen.dart | 33 ++++++-- .../search_employee_bottom_sheet.dart | 2 +- 11 files changed, 191 insertions(+), 67 deletions(-) create mode 100644 lib/models/chat/chat_count_conversation_model.dart diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index ead29d7..cedc158 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -7,6 +7,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:logger/logger.dart' as L; +import 'package:logging/logging.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -27,6 +28,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? pChatHistory, searchedChats; late HubConnection hubConnection; L.Logger logger = L.Logger(); + bool hubConInitialized = false; bool isLoading = true; bool isChatScreenActive = false; @@ -43,13 +45,27 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool _shouldAutoscroll = false; Future getUserAutoLoginToken() async { - String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString(); - //userName - Response response = - await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}user/desktopuserlogin", {"userName": userName, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "loginType": 2}); - login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(response.body); - AppState().setchatUserDetails = userLoginResponse; - await buildHubConnection(); + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", + { + "employeeNumber": int.parse( + AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + ), + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" + }, + ); + login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson( + response.body, + ); + + if (userLoginResponse.response != null) { + hubConInitialized = true; + AppState().setchatUserDetails = userLoginResponse; + await buildHubConnection(); + } else { + Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); + return; + } } Future?> getChatMemberFromSearch(String sName, int cUserId) async { @@ -95,6 +111,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { isLoading = true; + if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; isChatScreenActive = true; Response response = await ApiClient().getJsonForResponse( @@ -151,8 +168,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection = HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withAutomaticReconnect( - retryDelays: [2000, 5000, 10000, 20000], - ).build(); + retryDelays: [2000, 5000, 10000, 20000], + ) + .configureLogging(Logger("Loggin")) + .build(); hubConnection.onclose( ({Exception? error}) {}, ); @@ -173,6 +192,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + } } @@ -215,9 +235,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateChatHistoryWindow(List? args) { dynamic items = args!.toList(); - if (kDebugMode) { - print("---------------------------------Update Chat History Windows Async -------------------------------------"); - } + print("---------------------------------Update Chat History Windows Async -------------------------------------"); logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index cce2207..9747e5c 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -1,10 +1,12 @@ import 'dart:async'; import 'dart:convert'; +import 'package:http/http.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; +import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; @@ -15,7 +17,6 @@ import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:uuid/uuid.dart'; - class DashboardApiClient { static final DashboardApiClient _instance = DashboardApiClient._internal(); @@ -178,4 +179,11 @@ class DashboardApiClient { return responseData; }, url, postParams); } + + Future getChatCount() async { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}user/unreadconversationcount/${AppState().getUserName}", + ); + return chatUnreadCovnCountModelFromJson(response.body); + } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ 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 = "https://hmgwebservices.com"; // Live 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 static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; diff --git a/lib/models/chat/chat_count_conversation_model.dart b/lib/models/chat/chat_count_conversation_model.dart new file mode 100644 index 0000000..e584d32 --- /dev/null +++ b/lib/models/chat/chat_count_conversation_model.dart @@ -0,0 +1,25 @@ +import 'dart:convert'; + +ChatUnreadCovnCountModel chatUnreadCovnCountModelFromJson(String str) => ChatUnreadCovnCountModel.fromJson(json.decode(str)); + +String chatUnreadCovnCountModelToJson(ChatUnreadCovnCountModel data) => json.encode(data.toJson()); + +class ChatUnreadCovnCountModel { + ChatUnreadCovnCountModel({ + this.singleChatCount, + this.groupChatCount, + }); + + int? singleChatCount; + int? groupChatCount; + + factory ChatUnreadCovnCountModel.fromJson(Map json) => ChatUnreadCovnCountModel( + singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"], + groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"], + ); + + Map toJson() => { + "singleChatCount": singleChatCount == null ? null : singleChatCount, + "groupChatCount": groupChatCount == null ? null : groupChatCount, + }; +} diff --git a/lib/models/chat/get_user_login_token_model.dart b/lib/models/chat/get_user_login_token_model.dart index 8afd3a9..8d55461 100644 --- a/lib/models/chat/get_user_login_token_model.dart +++ b/lib/models/chat/get_user_login_token_model.dart @@ -1,4 +1,3 @@ - import 'dart:convert'; UserAutoLoginModel userAutoLoginModelFromJson(String str) => UserAutoLoginModel.fromJson(json.decode(str)); @@ -7,22 +6,22 @@ String userAutoLoginModelToJson(UserAutoLoginModel data) => json.encode(data.toJ class UserAutoLoginModel { UserAutoLoginModel({ - this.response, + this.response, this.errorResponses, }); Response? response; - dynamic? errorResponses; + List? errorResponses; factory UserAutoLoginModel.fromJson(Map json) => UserAutoLoginModel( - response: json["response"] == null ? null : Response.fromJson(json["response"]), - errorResponses: json["errorResponses"], - ); + response: json["response"] == null ? null : Response.fromJson(json["response"]), + errorResponses: json["errorResponses"] == null ? null : List.from(json["errorResponses"].map((x) => ErrorResponse.fromJson(x))), + ); Map toJson() => { - "response": response == null ? null : response!.toJson(), - "errorResponses": errorResponses, - }; + "response": response == null ? null : response!.toJson(), + "errorResponses": errorResponses == null ? null : List.from(errorResponses!.map((x) => x.toJson())), + }; } class Response { @@ -51,28 +50,48 @@ class Response { String? encryptedUserName; factory Response.fromJson(Map json) => Response( - id: json["id"] == null ? null : json["id"], - userName: json["userName"] == null ? null : json["userName"], - email: json["email"] == null ? null : json["email"], - phone: json["phone"] == null ? null : json["phone"], - title: json["title"] == null ? null : json["title"], - token: json["token"] == null ? null : json["token"], - isDomainUser: json["isDomainUser"] == null ? null : json["isDomainUser"], - isActiveCode: json["isActiveCode"] == null ? null : json["isActiveCode"], - encryptedUserId: json["encryptedUserId"] == null ? null : json["encryptedUserId"], - encryptedUserName: json["encryptedUserName"] == null ? null : json["encryptedUserName"], - ); + id: json["id"] == null ? null : json["id"], + userName: json["userName"] == null ? null : json["userName"], + email: json["email"] == null ? null : json["email"], + phone: json["phone"] == null ? null : json["phone"], + title: json["title"] == null ? null : json["title"], + token: json["token"] == null ? null : json["token"], + isDomainUser: json["isDomainUser"] == null ? null : json["isDomainUser"], + isActiveCode: json["isActiveCode"] == null ? null : json["isActiveCode"], + encryptedUserId: json["encryptedUserId"] == null ? null : json["encryptedUserId"], + encryptedUserName: json["encryptedUserName"] == null ? null : json["encryptedUserName"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "userName": userName == null ? null : userName, + "email": email == null ? null : email, + "phone": phone == null ? null : phone, + "title": title == null ? null : title, + "token": token == null ? null : token, + "isDomainUser": isDomainUser == null ? null : isDomainUser, + "isActiveCode": isActiveCode == null ? null : isActiveCode, + "encryptedUserId": encryptedUserId == null ? null : encryptedUserId, + "encryptedUserName": encryptedUserName == null ? null : encryptedUserName, + }; +} + +class ErrorResponse { + ErrorResponse({ + this.fieldName, + this.message, + }); + + String? fieldName; + String? message; + + factory ErrorResponse.fromJson(Map json) => ErrorResponse( + fieldName: json["fieldName"] == null ? null : json["fieldName"], + message: json["message"] == null ? null : json["message"], + ); Map toJson() => { - "id": id == null ? null : id, - "userName": userName == null ? null : userName, - "email": email == null ? null : email, - "phone": phone == null ? null : phone, - "title": title == null ? null : title, - "token": token == null ? null : token, - "isDomainUser": isDomainUser == null ? null : isDomainUser, - "isActiveCode": isActiveCode == null ? null : isActiveCode, - "encryptedUserId": encryptedUserId == null ? null : encryptedUserId, - "encryptedUserName": encryptedUserName == null ? null : encryptedUserName, - }; + "fieldName": fieldName == null ? null : fieldName, + "message": message == null ? null : message, + }; } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 5b9f8f1..b38536c 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.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/chat_count_conversation_model.dart'; import 'package:mohem_flutter_app/models/dashboard/drawer_menu_item_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; @@ -34,6 +35,10 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool isWorkListLoading = true; int workListCounter = 0; + //Chat + bool isChatCounterLoding = true; + int chatUConvCounter = 0; + //Misssing Swipe bool isMissingSwipeLoading = true; int missingSwipeCounter = 0; @@ -91,6 +96,9 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { accrualList = null; leaveBalanceAccrual = null; + isChatCounterLoding = true; + chatUConvCounter = 0; + ticketBalance = 0; isServicesMenusLoading = true; homeMenus = null; @@ -266,7 +274,19 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return res; } - + void fetchChatCounts() async { + print("----------------------- Fetch Count ____________________________________"); + try { + ChatUnreadCovnCountModel response = await DashboardApiClient().getChatCount(); + chatUConvCounter = response.singleChatCount!; + isChatCounterLoding = false; + notifyListeners(); + } catch (ex) { + logger.wtf(ex); + notifyListeners(); + Utils.handleException(ex, null, null); + } + } void notify() { notifyListeners(); diff --git a/lib/ui/chat/call/chat_call_screen.dart b/lib/ui/chat/call/chat_call_screen.dart index 0bec1f0..3fce65b 100644 --- a/lib/ui/chat/call/chat_call_screen.dart +++ b/lib/ui/chat/call/chat_call_screen.dart @@ -255,6 +255,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt // backToHome(); // final roomModel = RoomModel(name: widget.incomingCallData.name, token: widget.incomingCallData.sessionId, identity: widget.incomingCallData.identity); await _controller?.dispose(); + // changeCallStatusAPI(4); // if (_session != null && _signaling != null) { @@ -300,6 +301,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt // final connected = await signaling.declineCall(widget.incomingCallData.callerID, widget.incomingCallData.receiverID); // LandingPage.isOpenCallPage = false; // _signaling + _animationController!.dispose(); // player.stop(); // changeCallStatusAPI(3); // _signaling.bye(_session, callRejected: true); diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 6ddd19e..2ef61f0 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -34,15 +34,25 @@ class _ChatDetailScreenState extends State { void getMoreChat() async { if (userDetails != null) { data.paginationVal = data.paginationVal + 10; - data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false); + 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)); + await Future.delayed( + const Duration( + milliseconds: 1000, + ), + ); _rc.loadComplete(); } @override - void initState() { - super.initState(); + Widget build(BuildContext context) { + userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); if (userDetails != null) data.getSingleUserChatHistory( @@ -51,12 +61,6 @@ class _ChatDetailScreenState extends State { loadMore: false, isNewChat: userDetails["isNewChat"], ); - //data.scrollController.addListener(data.scrollListener); - } - - @override - Widget build(BuildContext context) { - userDetails = ModalRoute.of(context)!.settings.arguments; return Scaffold( backgroundColor: const Color(0xFFF8F8F8), appBar: AppBarWidget(context, @@ -66,7 +70,7 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - makeCall("AUDIO"); + // makeCall("AUDIO"); }, icon: SvgPicture.asset( "assets/images/call.svg", @@ -76,7 +80,7 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - makeCall("VIDEO"); + // makeCall("VIDEO"); }, icon: SvgPicture.asset( "assets/images/call.svg", diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 738fc17..744188f 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -1,6 +1,9 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.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/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -31,7 +34,7 @@ class _ChatHomeState extends State { // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((value) { + data.getUserAutoLoginToken().then((Object? value) { data.getUserRecentChats(); }); } @@ -39,7 +42,9 @@ class _ChatHomeState extends State { @override void dispose() { data.clearAll(); - data.hubConnection.stop(); + if (data.hubConInitialized) { + data.hubConnection.stop(); + } super.dispose(); } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index d342072..7453603 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -71,6 +71,7 @@ class _DashboardScreenState extends State { data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); data.getCategoryOffersListAPI(context); + data.fetchChatCounts(); _refreshController.refreshCompleted(); } @@ -268,7 +269,7 @@ class _DashboardScreenState extends State { ).onPress(() { showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: MarkAttendanceWidget(model, isFromDashboard: true), ); }), @@ -469,10 +470,32 @@ class _DashboardScreenState extends State { label: LocaleKeys.itemsForSale.tr(), ), BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/chat/chat.svg", - color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/chat/chat.svg", + color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, + ).paddingAll(4), + Consumer( + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + if (data.chatUConvCounter == 0) { + return const SizedBox(); + } + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.chatUConvCounter.toString().toText10(color: Colors.white), + ), + ); + }, + ), + ], + ), label: LocaleKeys.chat.tr(), ), ], diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index a30b33d..b88b96f 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -236,7 +236,7 @@ class _SearchEmployeeBottomSheetState extends State { arguments: {"targetUser": chatUsersList![index], "isNewChat": true}, ); }, - onLongPress: () {}, + ), ); },