From 468555046bccc7188fbfd5737180a69fc3df4ce3 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 20 Nov 2022 15:20:37 +0300 Subject: [PATCH 01/20] updates --- lib/ui/login/login_screen.dart | 1 + lib/widgets/mark_attendance_widget.dart | 60 ++++++++++++++++++------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 20fa8bc..68f0c41 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -128,6 +128,7 @@ class _LoginScreenState extends State { Navigator.pushNamed(context, AppRoutes.verifyLogin, arguments: "$firebaseToken"); } + Utils.saveStringFromPrefs(SharedPrefsConsts.password, password.text); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, (msg) { diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index c41b89c..a6b6cfc 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -14,6 +14,7 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/dialogs/success_dialog.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart'; import 'package:mohem_flutter_app/widgets/location/Location.dart'; import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart'; @@ -144,14 +145,28 @@ class _MarkAttendanceWidgetState extends State { Utils.showLoading(context); try { GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId, isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - bool status = await model.fetchAttendanceTracking(context); - Utils.hideLoading(context); - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: false, - child: SuccessDialog(widget.isFromDashboard), - ); + if(g?.messageStatus != 1) { + Utils.hideLoading(context); + showDialog( + context: context, + builder: (cxt) => ConfirmDialog( + message: g?.errorEndUserMessage ?? "Unexpected error occurred", + onTap: () { + Navigator.pop(context); + }, + ), + ); + } else { + bool status = await model.fetchAttendanceTracking(context); + Utils.hideLoading(context); + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); + } + } catch (ex) { print(ex); Utils.hideLoading(context); @@ -166,14 +181,27 @@ class _MarkAttendanceWidgetState extends State { Utils.showLoading(context); try { GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - bool status = await model.fetchAttendanceTracking(context); - Utils.hideLoading(context); - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: false, - child: SuccessDialog(widget.isFromDashboard), - ); + if(g?.messageStatus != 1) { + Utils.hideLoading(context); + showDialog( + context: context, + builder: (cxt) => ConfirmDialog( + message: g?.errorEndUserMessage ?? "Unexpected error occurred", + onTap: () { + Navigator.pop(context); + }, + ), + ); + } else { + bool status = await model.fetchAttendanceTracking(context); + Utils.hideLoading(context); + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); + } } catch (ex) { print(ex); Utils.hideLoading(context); From f4f9b442c857eccf75b8b49a3b41ea732825a8e9 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 15:47:42 +0300 Subject: [PATCH 02/20] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 57 +++++++++++-------- lib/models/chat/call.dart | 8 +-- .../chat/get_search_user_chat_model.dart | 32 ++++++----- lib/ui/chat/chat_detailed_screen.dart | 44 +++++++------- lib/ui/chat/chat_home_screen.dart | 18 +++++- 5 files changed, 96 insertions(+), 63 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 7a27c1f..a019294 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -115,6 +115,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { searchedChats = pChatHistory; isLoading = false; + getUserChatHistoryNotDeliveredAsync( + userId: int.parse( + AppState().chatDetails!.response!.id.toString(), + ), + ); notifyListeners(); } @@ -122,6 +127,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await hubConnection.invoke( "GetUserChatHistoryNotDeliveredAsync", args: [userId], + ).onError( + (Error error, StackTrace stackTrace) => { + logger.d(error), + }, ); return ""; } @@ -220,8 +229,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { '${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}', ), ); - request.fields.addAll({'userId': userId, 'fileSource': '1'}); - request.files.add(await MultipartFile.fromPath('files', file.path)); + request.fields.addAll( + {'userId': userId, 'fileSource': '1'}, + ); + request.files.add( + await MultipartFile.fromPath( + 'files', + file.path, + ), + ); request.headers.addAll( { 'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}', @@ -256,7 +272,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { options: httpOp, ) .withAutomaticReconnect( - retryDelays: [2000, 5000, 10000, 20000], + retryDelays: [ + 2000, + 5000, + 10000, + 20000, + ], ) .configureLogging( Logger("Loggin"), @@ -273,11 +294,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); if (hubConnection.state != HubConnectionState.Connected) { await hubConnection.start(); - getUserChatHistoryNotDeliveredAsync( - userId: int.parse( - AppState().chatDetails!.response!.id.toString(), - ), - ); + print("Connnnnn Stablished"); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); // hubConnection.on("OnSeenChatUserAsync", onChatSeen); @@ -343,21 +360,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); for (dynamic item in items[0]) { - searchedChats!.forEach((element) { - if (element.id == item["currentUserId"]) { - var val = element.unreadMessageCount == null ? 0 : element.unreadMessageCount; - element.unreadMessageCount = val! + 1; - } - }); - // dynamic data = [ - // { - // "userChatHistoryId": item["userChatHistoryId"], - // "TargetUserId": item["targetUserId"], - // "isDelivered": true, - // "isSeen": true, - // } - // ]; - // updateUserChatHistoryStatusAsync(data); + searchedChats!.forEach( + (ChatUser element) { + if (element.id == item["currentUserId"]) { + int? val = element.unreadMessageCount ?? 0; + element.unreadMessageCount = val! + 1; + } + element.isLoadingCounter = false; + }, + ); } notifyListeners(); } diff --git a/lib/models/chat/call.dart b/lib/models/chat/call.dart index 20f6a79..7f8f6eb 100644 --- a/lib/models/chat/call.dart +++ b/lib/models/chat/call.dart @@ -7,7 +7,7 @@ import 'dart:convert'; class CallDataModel { CallDataModel({ this.callerId, - this.callReciverId, + this.callReceiverID, this.notificationForeground, this.message, this.title, @@ -27,7 +27,7 @@ class CallDataModel { }); String? callerId; - String? callReciverId; + String? callReceiverID; String? notificationForeground; String? message; String? title; @@ -51,7 +51,7 @@ class CallDataModel { factory CallDataModel.fromJson(Map json) => CallDataModel( callerId: json["callerID"] == null ? null : json["callerID"], - callReciverId: json["callReciverID"] == null ? null : json["callReciverID"], + callReceiverID: json["callReceiverID"] == null ? null : json["callReceiverID"], notificationForeground: json["notification_foreground"] == null ? null : json["notification_foreground"], message: json["message"] == null ? null : json["message"], title: json["title"] == null ? null : json["title"], @@ -78,7 +78,7 @@ class CallDataModel { Map toJson() => { "callerID": callerId == null ? null : callerId, - "callReciverID": callReciverId == null ? null : callReciverId, + "callReceiverID": callReceiverID == null ? null : callReceiverID, "notification_foreground": notificationForeground == null ? null : notificationForeground, "message": message == null ? null : message, "title": title == null ? null : title, diff --git a/lib/models/chat/get_search_user_chat_model.dart b/lib/models/chat/get_search_user_chat_model.dart index ceee0de..31d1085 100644 --- a/lib/models/chat/get_search_user_chat_model.dart +++ b/lib/models/chat/get_search_user_chat_model.dart @@ -19,21 +19,21 @@ class ChatUserModel { } class ChatUser { - ChatUser({ - this.id, - this.userName, - this.email, - this.phone, - this.title, - this.userStatus, - this.image, - this.unreadMessageCount, - this.userAction, - this.isPin, - this.isFav, - this.isAdmin, - this.isTyping, - }); + ChatUser( + {this.id, + this.userName, + this.email, + this.phone, + this.title, + this.userStatus, + this.image, + this.unreadMessageCount, + this.userAction, + this.isPin, + this.isFav, + this.isAdmin, + this.isTyping, + this.isLoadingCounter}); int? id; String? userName; @@ -48,6 +48,7 @@ class ChatUser { bool? isFav; bool? isAdmin; bool? isTyping; + bool? isLoadingCounter; factory ChatUser.fromJson(Map json) => ChatUser( id: json["id"] == null ? null : json["id"], @@ -63,6 +64,7 @@ class ChatUser { isFav: json["isFav"] == null ? null : json["isFav"], isAdmin: json["isAdmin"] == null ? null : json["isAdmin"], isTyping: false, + isLoadingCounter: true, ); Map toJson() => { diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 4a8e70c..1374608 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -38,13 +38,14 @@ class _ChatDetailScreenState extends State { void getMoreChat() async { if (userDetails != null) { data.paginationVal = data.paginationVal + 10; - if (userDetails != null) + if (userDetails != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false, ); + } } await Future.delayed( const Duration( @@ -76,10 +77,10 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - // makeCall( - // callType: "AUDIO", - // con: data.hubConnection, - // ); + makeCall( + callType: "AUDIO", + con: data.hubConnection, + ); }, icon: SvgPicture.asset( "assets/icons/chat/call.svg", @@ -89,10 +90,10 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - // makeCall( - // callType: "VIDEO", - // con: data.hubConnection, - // ); + makeCall( + callType: "VIDEO", + con: data.hubConnection, + ); }, icon: SvgPicture.asset( "assets/icons/chat/video_call.svg", @@ -357,38 +358,41 @@ class _ChatDetailScreenState extends State { void makeCall({required String callType, required HubConnection con}) async { print("================== Make call Triggered ============================"); - logger.d(jsonEncode(AppState().chatDetails!.response)); Map json = { "callerID": AppState().chatDetails!.response!.id!.toString(), - "callReciverID": userDetails["targetUser"].id.toString(), + "callReceiverID": userDetails["targetUser"].id.toString(), "notification_foreground": "true", - "message": "Aamir is calling ", + "message": "Aamir is calling", "title": "Video Call", "type": callType == "VIDEO" ? "Video" : "Audio", - "identity": "Aamir.Muhammad", - "name": "Aamir Saleem Ahmad", + "identity": AppState().chatDetails!.response!.userName, + "name": AppState().chatDetails!.response!.title, "is_call": "true", "is_webrtc": "true", - "contant": "Start video Call Aamir.Muhammad", + "contant": "Start video Call ${AppState().chatDetails!.response!.userName}", "contantNo": "775d1f11-62d9-6fcc-91f6-21f8c14559fb", "chatEventId": "3", "fileTypeId": null, - "currentUserId": "266642", + "currentUserId": AppState().chatDetails!.response!.id!.toString(), "chatSource": "1", "userChatHistoryLineRequestList": [ - {"isSeen": false, "isDelivered": false, "targetUserId": 341682, "targetUserStatus": 4} + { + "isSeen": false, + "isDelivered": false, + "targetUserId": userDetails["targetUser"].id, + "targetUserStatus": 4, + } ], // "server": "https://192.168.8.163:8086", "server": "https://livecareturn.hmg.com:8086", }; - - CallDataModel incomingCallData = CallDataModel.fromJson(json); + CallDataModel callData = CallDataModel.fromJson(json); await Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => OutGoingCall( isVideoCall: callType == "VIDEO" ? true : false, - OutGoingCallData: incomingCallData, + OutGoingCallData: callData, ), ), ); diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 816aaec..63523f5 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -135,6 +135,22 @@ class _ChatHomeScreenState extends State { mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.max, children: [ + if (m.searchedChats![index].isLoadingCounter!) + Flexible( + child: Container( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + width: 18, + height: 18, + decoration: const BoxDecoration( + // color: MyColors.redColor, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: CircularProgressIndicator(), + ), + ), if (m.searchedChats![index].unreadMessageCount! > 0) Flexible( child: Container( @@ -193,7 +209,7 @@ class _ChatHomeScreenState extends State { AppRoutes.chatDetailed, arguments: {"targetUser": m.searchedChats![index], "isNewChat": false}, ).then((Object? value) { - // m.GetUserChatHistoryNotDeliveredAsync(userId: int.parse(AppState().chatDetails!.response!.id.toString())); + // m.GetUserChatHistoryNotDeliveredAsync(userId: int.parse(AppState().chatDetails!.response!.id.toString())); m.clearSelections(); m.notifyListeners(); }); From 622404896cf1df7f1e23323476bb7d8f4db76d48 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 16:44:23 +0300 Subject: [PATCH 03/20] Chat Updates & Counter Event Modifications --- lib/ui/chat/chat_detailed_screen.dart | 2 +- lib/ui/chat/chat_home.dart | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 1374608..787582d 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -69,7 +69,7 @@ class _ChatDetailScreenState extends State { } return Scaffold( - backgroundColor: const Color(0xFFF8F8F8), + backgroundColor: MyColors.backgroundColor, appBar: AppBarWidget(context, title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index b2db98a..4286f52 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -36,6 +36,11 @@ class _ChatHomeState extends State { data = Provider.of(context, listen: false); data.getUserAutoLoginToken(context).whenComplete(() { data.getUserRecentChats(); + // GetUserChatHistoryNotDeliveredAsync( + // userId: int.parse( + // AppState().chatDetails!.response!.id.toString(), + // ), + // ); }); } From dc9d1715d9fa70619493fee3b5e32ee8ca1bc8ff Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 16:44:55 +0300 Subject: [PATCH 04/20] Chat Updates & Counter Event Modifications --- lib/ui/chat/chat_home.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 4286f52..b2db98a 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -36,11 +36,6 @@ class _ChatHomeState extends State { data = Provider.of(context, listen: false); data.getUserAutoLoginToken(context).whenComplete(() { data.getUserRecentChats(); - // GetUserChatHistoryNotDeliveredAsync( - // userId: int.parse( - // AppState().chatDetails!.response!.id.toString(), - // ), - // ); }); } From eb7e5a4837db77c29e3ebab6e7db435a92583734 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 22 Nov 2022 12:28:17 +0300 Subject: [PATCH 05/20] Chat Updates & Stability --- lib/api/chat/chat_api_client.dart | 103 ++++++++ lib/main.dart | 2 +- .../chat_provider_model.dart | 240 +++++------------- lib/provider/dashboard_provider_model.dart | 15 ++ lib/ui/chat/chat_detailed_screen.dart | 7 +- lib/ui/chat/chat_home.dart | 9 +- lib/ui/chat/chat_home_screen.dart | 44 ++-- lib/ui/chat/favorite_users_screen.dart | 2 +- lib/ui/landing/dashboard_screen.dart | 31 +++ .../search_employee_bottom_sheet.dart | 10 +- 10 files changed, 247 insertions(+), 216 deletions(-) create mode 100644 lib/api/chat/chat_api_client.dart rename lib/{api/chat => provider}/chat_provider_model.dart (73%) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart new file mode 100644 index 0000000..0d1653d --- /dev/null +++ b/lib/api/chat/chat_api_client.dart @@ -0,0 +1,103 @@ +import 'dart:convert'; +import 'dart:io'; + +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/models/chat/get_search_user_chat_model.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as user; +import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; + +class ChatApiClient { + static final ChatApiClient _instance = ChatApiClient._internal(); + + ChatApiClient._internal(); + + factory ChatApiClient() => _instance; + + Future getUserLoginToken() async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", + { + "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + }, + ); + user.UserAutoLoginModel userLoginResponse = user.userAutoLoginModelFromJson( + response.body, + ); + return userLoginResponse; + } + + Future?> getChatMemberFromSearch(String sName, int cUserId) async { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId", + token: AppState().chatDetails!.response!.token, + ); + return searchUserJsonModel(response.body); + } + + List searchUserJsonModel(String str) => List.from( + json.decode(str).map((x) => ChatUser.fromJson(x)), + ); + + Future getRecentChats() async { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", + token: AppState().chatDetails!.response!.token, + ); + return ChatUserModel.fromJson( + json.decode(response.body), + ); + } + + Future getFavUsers() async { + Response favRes = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}", + token: AppState().chatDetails!.response!.token, + ); + return ChatUserModel.fromJson( + json.decode(favRes.body), + ); + } + + Future getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", + token: AppState().chatDetails!.response!.token, + ); + return response; + } + + Future favUser({required int userID, required int targetUserID}) async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", + { + "targetUserId": targetUserID, + "userId": userID, + }, + token: AppState().chatDetails!.response!.token); + fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + return favoriteChatUser; + } + + Future unFavUser({required int userID, required int targetUserID}) async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}FavUser/deleteFavUser", + {"targetUserId": targetUserID, "userId": userID}, + token: AppState().chatDetails!.response!.token, + ); + fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + return favoriteChatUser; + } + + Future uploadMedia(String userId, File file) async { + dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}')); + request.fields.addAll({'userId': userId, 'fileSource': '1'}); + request.files.add(await MultipartFile.fromPath('files', file.path)); + request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); + StreamedResponse response = await request.send(); + return response; + } +} diff --git a/lib/main.dart b/lib/main.dart index a2ae0ae..4d686b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; -import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/codegen_loader.g.dart'; diff --git a/lib/api/chat/chat_provider_model.dart b/lib/provider/chat_provider_model.dart similarity index 73% rename from lib/api/chat/chat_provider_model.dart rename to lib/provider/chat_provider_model.dart index a019294..01eb0ad 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1,21 +1,21 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; - import 'package:easy_localization/easy_localization.dart'; 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/api/chat/chat_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/utils.dart'; +import 'package:mohem_flutter_app/main.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/models/chat/get_user_login_token_model.dart' as login; import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; +import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/widgets/image_picker.dart'; import 'package:signalr_netcore/signalr_client.dart'; import 'package:uuid/uuid.dart'; @@ -26,9 +26,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { TextEditingController search = TextEditingController(); List userChatHistory = []; List? pChatHistory, searchedChats; - late HubConnection hubConnection; - L.Logger logger = L.Logger(); - bool hubConInitialized = false; String chatCID = ''; bool isLoading = true; bool isChatScreenActive = false; @@ -40,56 +37,20 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; - Future getUserAutoLoginToken(BuildContext cxt) async { - Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", - { - "employeeNumber": 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 { - Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId", - token: AppState().chatDetails!.response!.token, - ); - return searchUserJsonModel(response.body); + void registerEvents() { + hubConnection.on("OnUpdateUserStatusAsync", changeStatus); + hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); + // hubConnection.on("OnSeenChatUserAsync", onChatSeen); + //hubConnection.on("OnUserTypingAsync", onUserTyping); + hubConnection.on("OnUserCountAsync", userCountAsync); + hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); + hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } - List searchUserJsonModel(String str) => List.from( - json.decode(str).map( - (x) => ChatUser.fromJson(x), - ), - ); - void getUserRecentChats() async { - Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", - token: AppState().chatDetails!.response!.token, - ); - ChatUserModel recentChat = userToList(response.body); - - Response favRes = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}", - token: AppState().chatDetails!.response!.token, - ); - ChatUserModel favUList = userToList(favRes.body); + ChatUserModel recentChat = await ChatApiClient().getRecentChats(); + ChatUserModel favUList = await ChatApiClient().getFavUsers(); if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; @@ -108,14 +69,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } pChatHistory = recentChat.response ?? []; pChatHistory!.sort( - (ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo( - b.userName!.toLowerCase(), - ), + (ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()), ); - searchedChats = pChatHistory; isLoading = false; - getUserChatHistoryNotDeliveredAsync( + await getUserChatHistoryNotDeliveredAsync( userId: int.parse( AppState().chatDetails!.response!.id.toString(), ), @@ -124,14 +82,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future getUserChatHistoryNotDeliveredAsync({required int userId}) async { - await hubConnection.invoke( - "GetUserChatHistoryNotDeliveredAsync", - args: [userId], - ).onError( - (Error error, StackTrace stackTrace) => { - logger.d(error), - }, - ); + // try { + await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); + // } finally { + // hubConnection.off("OnGetUserChatHistoryNotDeliveredAsync", method: chatNotDelivered); + // } + return ""; } @@ -140,9 +96,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; isChatScreenActive = true; - Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", - token: AppState().chatDetails!.response!.token, + Response response = await ChatApiClient().getSingleUserChatHistory( + senderUID: senderUID, + receiverUID: receiverUID, + loadMore: loadMore, + paginationVal: paginationVal, ); if (response.statusCode == 204) { if (isNewChat) { @@ -165,9 +123,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ).reversed.toList(); } } - await getUserChatHistoryNotDeliveredAsync( - userId: senderUID, - ); isLoading = false; notifyListeners(); markRead( @@ -184,16 +139,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void markRead(List data, reciverID) { for (SingleUserChatModel element in data!) { - if (!element.isSeen!) { - dynamic data = [ - { - "userChatHistoryId": element.userChatHistoryId, - "TargetUserId": element.targetUserId, - "isDelivered": true, - "isSeen": true, - } - ]; - updateUserChatHistoryStatusAsync(data); + if (element.isSeen != null) { + if (!element.isSeen!) { + dynamic data = [ + { + "userChatHistoryId": element.userChatHistoryId, + "TargetUserId": element.targetUserId, + "isDelivered": true, + "isSeen": true, + } + ]; + updateUserChatHistoryStatusAsync(data); + } } } for (ChatUser element in searchedChats!) { @@ -217,34 +174,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ), ); - ChatUserModel userToList(String str) => ChatUserModel.fromJson( - json.decode(str), - ); - Future uploadAttachments(String userId, File file) async { dynamic result; - dynamic request = MultipartRequest( - 'POST', - Uri.parse( - '${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}', - ), - ); - request.fields.addAll( - {'userId': userId, 'fileSource': '1'}, - ); - request.files.add( - await MultipartFile.fromPath( - 'files', - file.path, - ), - ); - request.headers.addAll( - { - 'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}', - }, - ); try { - StreamedResponse response = await request.send(); + StreamedResponse response = await ChatApiClient().uploadMedia(userId, file); if (response.statusCode == 200) { result = jsonDecode( await response.stream.bytesToString(), @@ -253,60 +186,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { result = []; } } catch (e) { - if (kDebugMode) { - print(e); - } + print(e); } ; return result; } - Future buildHubConnection() async { - HttpConnectionOptions httpOp = HttpConnectionOptions( - skipNegotiation: false, - logMessageContent: true, - ); - 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, - ], - ) - .configureLogging( - Logger("Loggin"), - ) - .build(); - hubConnection.onclose( - ({Exception? error}) {}, - ); - hubConnection.onreconnecting( - ({Exception? error}) {}, - ); - hubConnection.onreconnected( - ({String? connectionId}) {}, - ); - if (hubConnection.state != HubConnectionState.Connected) { - await hubConnection.start(); - print("Connnnnn Stablished"); - hubConnection.on("OnUpdateUserStatusAsync", changeStatus); - hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - // hubConnection.on("OnSeenChatUserAsync", onChatSeen); - - //hubConnection.on("OnUserTypingAsync", onUserTyping); - hubConnection.on("OnUserCountAsync", userCountAsync); - hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); - hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); - } - } - void updateUserChatStatus(List? args) { dynamic items = args!.toList(); for (dynamic cItem in items[0]) { @@ -359,6 +244,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); + logger.d(items); for (dynamic item in items[0]) { searchedChats!.forEach( (ChatUser element) { @@ -374,11 +260,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void changeStatus(List? args) { - if (kDebugMode) { - // print("================= Status Online // Offline ===================="); - } dynamic items = args!.toList(); - // logger.d(items); for (ChatUser user in searchedChats!) { if (user.id == items.first["id"]) { user.userStatus = items.first["userStatus"]; @@ -413,14 +295,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserId = temp.first.targetUserId; data.first.currentUserName = temp.first.targetUserName; } + logger.d(jsonEncode(data)); userChatHistory.insert(0, data.first); - // searchedChats!.forEach((element) { - // if (element.id == data.first.currentUserId) { - // var val = element.unreadMessageCount == null ? 0 : element.unreadMessageCount; - // element.unreadMessageCount = val! + 1; - // } - // }); - var list = [ { "userChatHistoryId": data.first.userChatHistoryId, @@ -430,14 +306,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } ]; updateUserChatHistoryStatusAsync(list); - notifyListeners(); - // if (isChatScreenActive) scrollToBottom(); } void onUserTyping(List? parameters) { - // print("==================== Typing Active =================="); - // logger.d(parameters); for (ChatUser user in searchedChats!) { if (user.id == parameters![1] && parameters[0] == true) { user.isTyping = parameters[0] as bool?; @@ -572,7 +444,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } if (!isFileSelected && !isMsgReply) { - logger.d("Normal Text Message"); if (message.text == null || message.text.isEmpty) { return; } @@ -580,14 +451,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (isFileSelected && !isMsgReply) { Utils.showLoading(context); - //logger.d("Normal Attachment Message"); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false); } if (!isFileSelected && isMsgReply) { - // logger.d("Normal Text Message With Reply"); if (message.text == null || message.text.isEmpty) { return; } @@ -595,7 +464,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true); } if (isFileSelected && isMsgReply) { - // logger.d("Attachment Message With Reply"); Utils.showLoading(context); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); @@ -708,9 +576,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future favoriteUser({required int userID, required int targetUserID}) async { - Response response = - await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); - fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().favUser(userID: userID, targetUserID: targetUserID); if (favoriteChatUser.response != null) { for (ChatUser user in searchedChats!) { if (user.id == favoriteChatUser.response!.targetUserId!) { @@ -723,16 +589,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future unFavoriteUser({required int userID, required int targetUserID}) async { - Response response = await ApiClient() - .postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/deleteFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); - fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().unFavUser(userID: userID, targetUserID: targetUserID); if (favoriteChatUser.response != null) { - for (var user in searchedChats!) { + for (ChatUser user in searchedChats!) { if (user.id == favoriteChatUser.response!.targetUserId!) { user.isFav = favoriteChatUser.response!.isFav; } } - favUsersList.removeWhere((ChatUser element) => element.id == targetUserID); + favUsersList.removeWhere( + (ChatUser element) => element.id == targetUserID, + ); } notifyListeners(); } @@ -784,4 +650,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { curve: Curves.easeIn, ); } + +// void getUserChatHistoryNotDeliveredAsync({required int userId}) async { +// try { +// await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); +// } finally { +// hubConnection.off("GetUserChatHistoryNotDeliveredAsync", method: chatNotDelivered); +// } +// } } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 948e5b4..e0c90c9 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -1,13 +1,16 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/chat/chat_api_client.dart'; import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/api/offers_and_discounts_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; 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/chat/get_user_login_token_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'; @@ -287,6 +290,18 @@ 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; + } else { + Utils.showToast( + userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + ); + } + } + void notify() { notifyListeners(); } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 787582d..a3cf2e9 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -4,7 +4,7 @@ import 'dart:convert'; 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/provider/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/int_extensions.dart'; @@ -15,6 +15,7 @@ import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.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/landing/dashboard_screen.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'; @@ -79,7 +80,7 @@ class _ChatDetailScreenState extends State { onPressed: () { makeCall( callType: "AUDIO", - con: data.hubConnection, + con: hubConnection, ); }, icon: SvgPicture.asset( @@ -92,7 +93,7 @@ class _ChatDetailScreenState extends State { onPressed: () { makeCall( callType: "VIDEO", - con: data.hubConnection, + con: hubConnection, ); }, icon: SvgPicture.asset( diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index b2db98a..3ad9b12 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -2,7 +2,7 @@ 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/provider/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'; @@ -31,21 +31,14 @@ class _ChatHomeState extends State { @override void initState() { - // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken(context).whenComplete(() { - data.getUserRecentChats(); - }); } @override void dispose() { super.dispose(); data.clearAll(); - if (data.hubConInitialized) { - data.hubConnection.stop(); - } } @override diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 63523f5..a6f91b8 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.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/provider/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'; @@ -21,6 +21,16 @@ class ChatHomeScreen extends StatefulWidget { class _ChatHomeScreenState extends State { TextEditingController search = TextEditingController(); + late ChatProviderModel data; + + @override + void initState() { + // TODO: implement initState + super.initState(); + data = Provider.of(context, listen: false); + data.registerEvents(); + data.getUserRecentChats(); + } @override void dispose() { @@ -135,22 +145,22 @@ class _ChatHomeScreenState extends State { mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.max, children: [ - if (m.searchedChats![index].isLoadingCounter!) - Flexible( - child: Container( - padding: EdgeInsets.zero, - alignment: Alignment.centerRight, - width: 18, - height: 18, - decoration: const BoxDecoration( - // color: MyColors.redColor, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), - ), - child: CircularProgressIndicator(), - ), - ), + // if (m.searchedChats![index].isLoadingCounter!) + // Flexible( + // child: Container( + // padding: EdgeInsets.zero, + // alignment: Alignment.centerRight, + // width: 18, + // height: 18, + // decoration: const BoxDecoration( + // // color: MyColors.redColor, + // borderRadius: BorderRadius.all( + // Radius.circular(20), + // ), + // ), + // child: CircularProgressIndicator(), + // ), + // ), if (m.searchedChats![index].unreadMessageCount! > 0) Flexible( child: Container( diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 7ef0f84..8f303cd 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/cupertino.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/provider/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/classes/utils.dart'; diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 130c75b..52b5ade 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -7,6 +7,7 @@ import 'package:flutter_countdown_timer/flutter_countdown_timer.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/classes/consts.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -26,6 +27,9 @@ import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart' import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:signalr_netcore/signalr_client.dart'; + +late HubConnection hubConnection; class DashboardScreen extends StatefulWidget { DashboardScreen({Key? key}) : super(key: key); @@ -49,13 +53,40 @@ class _DashboardScreenState extends State { super.initState(); scheduleMicrotask(() { data = Provider.of(context, listen: false); + data.getUserAutoLoginToken().whenComplete(() { + buildHubConnection(); + }); + _onRefresh(); }); } + Future buildHubConnection() async { + logger.d("Connnnnn Statred"); + HttpConnectionOptions httpOp = HttpConnectionOptions( + skipNegotiation: false, + logMessageContent: true, + ); + 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(); + hubConnection.onclose(({Exception? error}) { + logger.d("Con Closedddddd"); + }); + hubConnection.onreconnecting(({Exception? error}) {}); + hubConnection.onreconnected(({String? connectionId}) {}); + + if (hubConnection.state != HubConnectionState.Connected) { + await hubConnection.start(); + } + + + } + @override void dispose() { super.dispose(); + hubConnection.stop(); } void _onRefresh() async { diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index b88b96f..32b501c 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -5,7 +5,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; +import 'package:mohem_flutter_app/api/chat/chat_api_client.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -88,7 +88,12 @@ class _SearchEmployeeBottomSheetState extends State { void fetchChatUser({bool isNeedLoading = true}) async { try { Utils.showLoading(context); - chatUsersList = await ChatProviderModel().getChatMemberFromSearch(searchText, int.parse(AppState().chatDetails!.response!.id.toString())); + chatUsersList = await ChatApiClient().getChatMemberFromSearch( + searchText, + int.parse( + AppState().chatDetails!.response!.id.toString(), + ), + ); Utils.hideLoading(context); setState(() {}); } catch (e) { @@ -236,7 +241,6 @@ class _SearchEmployeeBottomSheetState extends State { arguments: {"targetUser": chatUsersList![index], "isNewChat": true}, ); }, - ), ); }, From 68ebecf98ab9f2effaf7b097257d5a7c0175cfa2 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 22 Nov 2022 12:49:42 +0300 Subject: [PATCH 06/20] Chat Updates & Stability --- lib/provider/dashboard_provider_model.dart | 14 ++++++++++++ lib/ui/landing/dashboard_screen.dart | 26 +++++----------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index e0c90c9..b785293 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -5,6 +5,7 @@ import 'package:mohem_flutter_app/api/chat/chat_api_client.dart'; import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/api/offers_and_discounts_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/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; @@ -24,6 +25,7 @@ import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; +import 'package:signalr_netcore/signalr_client.dart'; /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool // ignore: prefer_mixin @@ -40,6 +42,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Chat bool isChatCounterLoding = true; + bool isChatHubLoding = true; int chatUConvCounter = 0; //Misssing Swipe @@ -100,6 +103,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { leaveBalanceAccrual = null; isChatCounterLoding = true; + isChatHubLoding = true; chatUConvCounter = 0; ticketBalance = 0; @@ -302,6 +306,16 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + Future getHubConnection() async { + HubConnection hub; + HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); + hub = 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(); + isChatHubLoding = false; + return hub; + } + void notify() { notifyListeners(); } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 52b5ade..2de3310 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -56,31 +56,15 @@ class _DashboardScreenState extends State { data.getUserAutoLoginToken().whenComplete(() { buildHubConnection(); }); - _onRefresh(); }); } - Future buildHubConnection() async { - logger.d("Connnnnn Statred"); - HttpConnectionOptions httpOp = HttpConnectionOptions( - skipNegotiation: false, - logMessageContent: true, - ); - 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(); - hubConnection.onclose(({Exception? error}) { - logger.d("Con Closedddddd"); - }); - hubConnection.onreconnecting(({Exception? error}) {}); - hubConnection.onreconnected(({String? connectionId}) {}); - - if (hubConnection.state != HubConnectionState.Connected) { - await hubConnection.start(); - } - - + void buildHubConnection() async { + logger.d("Connection In Progresssss"); + hubConnection = await data.getHubConnection(); + await hubConnection.start(); + logger.d("Connection Done"); } @override From ed15ce92b6759fb378956ee49cccacc6613288ec Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 22 Nov 2022 12:50:59 +0300 Subject: [PATCH 07/20] Chat Updates & Stability --- lib/ui/landing/dashboard_screen.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 2de3310..3007c88 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -61,10 +61,8 @@ class _DashboardScreenState extends State { } void buildHubConnection() async { - logger.d("Connection In Progresssss"); hubConnection = await data.getHubConnection(); await hubConnection.start(); - logger.d("Connection Done"); } @override From 6a0c4884355261813db29f2914746c3fb9af23ae Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 24 Nov 2022 11:33:16 +0300 Subject: [PATCH 08/20] translation fix --- lib/ui/attendance/add_vacation_rule_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index caa1ee3..5d4bf75 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -316,7 +316,7 @@ class _AddVacationRuleScreenState extends State { 12.height, PopupMenuButton( child: DynamicTextFieldWidget( - "Notification", + LocaleKeys.notification.tr(), selectedItemTypeNotification == null ? LocaleKeys.selectNotification.tr() : selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!, isEnable: false, isPopup: true, From db3e1427c5299217bd4c21c5c0baca235a335b79 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 24 Nov 2022 16:29:28 +0300 Subject: [PATCH 09/20] Advertisement Image/ Video Module --- lib/classes/consts.dart | 4 +- lib/provider/chat_provider_model.dart | 47 +++--- lib/ui/chat/chat_bubble.dart | 12 +- lib/ui/landing/dashboard_screen.dart | 86 +++++------ .../itg/its_add_screen_video_image.dart | 138 ++++++++++++++++++ lib/ui/landing/itg/video_page.dart | 96 ------------ 6 files changed, 213 insertions(+), 170 deletions(-) create mode 100644 lib/ui/landing/itg/its_add_screen_video_image.dart delete mode 100644 lib/ui/landing/itg/video_page.dart diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..ede22e3 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/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 01eb0ad..81cb8b5 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -73,7 +73,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); searchedChats = pChatHistory; isLoading = false; - await getUserChatHistoryNotDeliveredAsync( + await invokeUserChatHistoryNotDeliveredAsync( userId: int.parse( AppState().chatDetails!.response!.id.toString(), ), @@ -81,13 +81,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - Future getUserChatHistoryNotDeliveredAsync({required int userId}) async { - // try { + Future invokeUserChatHistoryNotDeliveredAsync({required int userId}) async { await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); - // } finally { - // hubConnection.off("OnGetUserChatHistoryNotDeliveredAsync", method: chatNotDelivered); - // } - return ""; } @@ -137,26 +132,28 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatCID = uuid.v4(); } - void markRead(List data, reciverID) { - for (SingleUserChatModel element in data!) { - if (element.isSeen != null) { - if (!element.isSeen!) { - dynamic data = [ - { - "userChatHistoryId": element.userChatHistoryId, - "TargetUserId": element.targetUserId, - "isDelivered": true, - "isSeen": true, - } - ]; - updateUserChatHistoryStatusAsync(data); + void markRead(List data, int receiverID) { + if (data != null) { + for (SingleUserChatModel element in data!) { + if (element.isSeen != null) { + if (!element.isSeen!) { + dynamic data = [ + { + "userChatHistoryId": element.userChatHistoryId, + "TargetUserId": element.targetUserId, + "isDelivered": true, + "isSeen": true, + } + ]; + updateUserChatHistoryStatusAsync(data); + } } } - } - for (ChatUser element in searchedChats!) { - if (element.id == reciverID) { - element.unreadMessageCount = 0; - notifyListeners(); + for (ChatUser element in searchedChats!) { + if (element.id == receiverID) { + element.unreadMessageCount = 0; + notifyListeners(); + } } } } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 1696a49..1f6e5dd 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -132,12 +132,12 @@ class ChatBubble extends StatelessWidget { color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7), ), if (isCurrentUser) 5.width, - // if (isCurrentUser) - // Icon( - // isDelivered ? Icons.done_all : Icons.done_all, - // color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, - // size: 14, - // ), + if (isCurrentUser) + Icon( + isDelivered ? Icons.done_all : Icons.done_all, + color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, + size: 14, + ), ], ), ], diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 3007c88..d433e09 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -1,10 +1,12 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -17,6 +19,7 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/widget/app_drawer.dart'; import 'package:mohem_flutter_app/ui/landing/widget/menus_widget.dart'; import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart'; @@ -53,9 +56,7 @@ class _DashboardScreenState extends State { super.initState(); scheduleMicrotask(() { data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().whenComplete(() { - buildHubConnection(); - }); + _bHubCon(); _onRefresh(); }); } @@ -71,6 +72,12 @@ class _DashboardScreenState extends State { hubConnection.stop(); } + void _bHubCon() { + data.getUserAutoLoginToken().whenComplete(() { + buildHubConnection(); + }); + } + void _onRefresh() async { data.initProvider(); // data.getITGNotification().then((value) { @@ -93,44 +100,41 @@ class _DashboardScreenState extends State { Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, - // appBar: AppBar( - // actions: [ - // IconButton( - // onPressed: () { - // data.getITGNotification().then((value) { - // print("--------------------detail_1-----------------"); - // if (value!.result!.data != null) { - // print(value.result!.data!.notificationMasterId); - // print(value.result!.data!.notificationType); - // if (value.result!.data!.notificationType == "Survey") { - // Navigator.pushNamed(context, AppRoutes.survey, arguments: value.result!.data); - // } else { - // DashboardApiClient().getAdvertisementDetail(value.result!.data!.notificationMasterId ?? "").then( - // (value) { - // if (value!.mohemmItgResponseItem!.statusCode == 200) { - // if (value.mohemmItgResponseItem!.result!.data != null) { - // String? image64 = value.mohemmItgResponseItem!.result!.data!.advertisement!.viewAttachFileColl!.first.base64String; - // print(image64); - // var sp = image64!.split("base64,"); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => MovieTheaterBody( - // encodedBytes: sp[1], - // ), - // ), - // ); - // } - // } - // }, - // ); - // } - // } - // }); - // }, - // icon: Icon(Icons.add)) - // ], - // ), + appBar: AppBar( + actions: [ + IconButton( + onPressed: () { + data.getITGNotification().then((value) { + if (value!.result!.data != null) { + if (value.result!.data!.notificationType == "Survey") { + Navigator.pushNamed(context, AppRoutes.survey, arguments: value.result!.data); + } else { + DashboardApiClient().getAdvertisementDetail(value.result!.data!.notificationMasterId ?? "").then( + (value) { + if (value!.mohemmItgResponseItem!.statusCode == 200) { + if (value.mohemmItgResponseItem!.result!.data != null) { + String? rFile = value.mohemmItgResponseItem!.result!.data!.advertisement!.viewAttachFileColl!.first.base64String; + String? rFileExt = value.mohemmItgResponseItem!.result!.data!.advertisement!.viewAttachFileColl!.first.fileName; + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => ITGAdsScreen( + encodedBytes: rFile!, + fileExtenshion: rFileExt!, + ), + ), + ); + } + } + }, + ); + } + } + }); + }, + icon: Icon(Icons.add)) + ], + ), body: Column( children: [ Row( diff --git a/lib/ui/landing/itg/its_add_screen_video_image.dart b/lib/ui/landing/itg/its_add_screen_video_image.dart new file mode 100644 index 0000000..1d9c41f --- /dev/null +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -0,0 +1,138 @@ +import 'dart:convert'; +import 'dart:io' as Io; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:video_player/video_player.dart'; + +class ITGAdsScreen extends StatefulWidget { + final String encodedBytes; + final String fileExtension; + + const ITGAdsScreen({required this.encodedBytes, required this.fileExtension}); + + @override + _ITGAdsScreenState createState() => _ITGAdsScreenState(); +} + +class _ITGAdsScreenState extends State { + late Future _futureController; + late VideoPlayerController _controller; + bool skip = false; + + Future createVideoPlayer() async { + try { + Uint8List decodedBytes = base64Decode(widget.encodedBytes.split("base64,").last); + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 + File file = Io.File("${appDocumentsDirectory.path}/myAdsVideo.mp4"); + file.writeAsBytesSync(decodedBytes); + VideoPlayerController controller = VideoPlayerController.file(file); + await controller.initialize(); + await controller.play(); + await controller.setVolume(1.0); + await controller.setLooping(false); + return controller; + } catch (e) { + return new VideoPlayerController.asset("dataSource"); + } + } + + void checkType(){ + + // getFileTypeDescription(value); + + + } + + String getFileTypeDescription(String value) { + switch (value) { + case ".pdf": + return "application/pdf"; + case ".png": + return "image/png"; + case ".txt": + return "text/plain"; + case ".jpg": + return "image/jpg"; + case ".jpeg": + return "image/jpeg"; + case ".ppt": + return "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + case ".pptx": + return "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + case ".doc": + return "application/vnd.openxmlformats-officedocument.wordprocessingm"; + case ".docx": + return "application/vnd.openxmlformats-officedocument.wordprocessingm"; + case ".xls": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + case ".xlsx": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + case ".zip": + return "application/octet-stream"; + case ".rar": + return "application/octet-stream"; + default: + return ""; + } + } + + @override + void initState() { + _futureController = createVideoPlayer(); + initTimer(); + super.initState(); + } + + void initTimer() { + Future.delayed(const Duration(milliseconds: 500), () { + setState(() { + skip = true; + }); + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + double height = MediaQuery.of(context).size.height * .25; + return Scaffold( + body: Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .3, + child: FutureBuilder( + future: _futureController, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) { + _controller = snapshot.data as VideoPlayerController; + return AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: VideoPlayer(_controller), + ); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + ), + ), + if (skip) + ElevatedButton( + onPressed: () {}, + child: const Text("Go To Dashboard"), + ) + ], + ), + ); + } +} diff --git a/lib/ui/landing/itg/video_page.dart b/lib/ui/landing/itg/video_page.dart deleted file mode 100644 index 657d714..0000000 --- a/lib/ui/landing/itg/video_page.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'dart:convert'; -import 'dart:io' as Io; - -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; - -class MovieTheaterBody extends StatefulWidget { - final String encodedBytes; - - const MovieTheaterBody({required this.encodedBytes}); - - @override - _MovieTheaterBodyState createState() => _MovieTheaterBodyState(); -} - -class _MovieTheaterBodyState extends State { - late Future _futureController; - late VideoPlayerController _controller; - - Future createVideoPlayer() async { - try { - var decodedBytes = base64Decode(widget.encodedBytes); - - var file = Io.File("decodedBezkoder.mp4"); - file.writeAsBytesSync(decodedBytes); - - VideoPlayerController controller = VideoPlayerController.file(file); - await controller.initialize(); - await controller.setLooping(true); - return controller; - } catch (e) { - print("object0000000"); - print(e); - return new VideoPlayerController.asset("dataSource"); - } - } - - @override - void initState() { - _futureController = createVideoPlayer(); - super.initState(); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Expanded( - child: FutureBuilder( - future: _futureController, - builder: (context, snapshot) { - //UST: 05/2021 - MovieTheaterBody - id:11 - 2pts - Criação - if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) { - _controller = snapshot.data as VideoPlayerController; - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AspectRatio( - aspectRatio: _controller.value.aspectRatio, - child: VideoPlayer(_controller), - ), - const SizedBox( - height: 50, - ), - FloatingActionButton( - onPressed: () { - setState(() { - if (_controller.value.isPlaying) { - _controller.pause(); - } else { - // If the video is paused, play it. - _controller.play(); - } - }); - }, - backgroundColor: Colors.green[700], - child: Icon( - _controller.value.isPlaying ? Icons.pause : Icons.play_arrow, - ), - ) - ], - ); - } else { - return const Center(child: CircularProgressIndicator()); - } - }, - ), - ), - ); - } -} From fa7e08c215860c6a6d106766a2def51858a46eb5 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 27 Nov 2022 10:23:02 +0300 Subject: [PATCH 10/20] Advertisement Image/ Video Module --- lib/api/dashboard_api_client.dart | 14 ++ lib/ui/landing/dashboard_screen.dart | 68 +++++---- .../itg/its_add_screen_video_image.dart | 132 +++++++++--------- 3 files changed, 112 insertions(+), 102 deletions(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 9747e5c..69c2e82 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -186,4 +186,18 @@ class DashboardApiClient { ); 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); + // } } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index d433e09..c8cdcef 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -100,41 +100,39 @@ class _DashboardScreenState extends State { Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, - appBar: AppBar( - actions: [ - IconButton( - onPressed: () { - data.getITGNotification().then((value) { - if (value!.result!.data != null) { - if (value.result!.data!.notificationType == "Survey") { - Navigator.pushNamed(context, AppRoutes.survey, arguments: value.result!.data); - } else { - DashboardApiClient().getAdvertisementDetail(value.result!.data!.notificationMasterId ?? "").then( - (value) { - if (value!.mohemmItgResponseItem!.statusCode == 200) { - if (value.mohemmItgResponseItem!.result!.data != null) { - String? rFile = value.mohemmItgResponseItem!.result!.data!.advertisement!.viewAttachFileColl!.first.base64String; - String? rFileExt = value.mohemmItgResponseItem!.result!.data!.advertisement!.viewAttachFileColl!.first.fileName; - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => ITGAdsScreen( - encodedBytes: rFile!, - fileExtenshion: rFileExt!, - ), - ), - ); - } - } - }, - ); - } - } - }); - }, - icon: Icon(Icons.add)) - ], - ), + // appBar: AppBar( + // actions: [ + // IconButton( + // onPressed: () { + // data.getITGNotification().then((val) { + // if (val!.result!.data != null) { + // if (val.result!.data!.notificationType == "Survey") { + // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + // } else { + // DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( + // (value) { + // if (value!.mohemmItgResponseItem!.statusCode == 200) { + // if (value.mohemmItgResponseItem!.result!.data != null) { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (BuildContext context) => ITGAdsScreen( + // addMasterId: val.result!.data!.notificationMasterId!, + // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, + // ), + // ), + // ); + // } + // } + // }, + // ); + // } + // } + // }); + // }, + // icon: Icon(Icons.add)) + // ], + // ), body: Column( children: [ Row( diff --git a/lib/ui/landing/itg/its_add_screen_video_image.dart b/lib/ui/landing/itg/its_add_screen_video_image.dart index 1d9c41f..4b2e358 100644 --- a/lib/ui/landing/itg/its_add_screen_video_image.dart +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -2,17 +2,20 @@ import 'dart:convert'; import 'dart:io' as Io; import 'dart:io'; import 'dart:typed_data'; - import 'package:flutter/material.dart'; +import 'package:just_audio/just_audio.dart'; +import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads; import 'package:path_provider/path_provider.dart'; import 'package:video_player/video_player.dart'; class ITGAdsScreen extends StatefulWidget { - final String encodedBytes; - final String fileExtension; + final String addMasterId; + final ads.Advertisement advertisement; - const ITGAdsScreen({required this.encodedBytes, required this.fileExtension}); + const ITGAdsScreen({required this.addMasterId, required this.advertisement}); @override _ITGAdsScreenState createState() => _ITGAdsScreenState(); @@ -22,10 +25,39 @@ class _ITGAdsScreenState extends State { late Future _futureController; late VideoPlayerController _controller; bool skip = false; + bool isVideo = false; + bool isImage = false; + String ext = ''; + late File imageFile; + + void checkFileType() async { + String? rFile = widget.advertisement!.viewAttachFileColl!.first.base64String; + String? rFileExt = widget.advertisement!.viewAttachFileColl!.first.fileName; + ext = "." + rFileExt!.split(".").last.toLowerCase(); + if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") { + await processImage(rFile!); + isImage = true; + } else { + isVideo = true; + _futureController = createVideoPlayer(rFile!); + } + setState(() {}); + } + + Future processImage(String encodedBytes) async { + try { + Uint8List decodedBytes = base64Decode(encodedBytes.split("base64,").last); + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 + imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext"); + imageFile.writeAsBytesSync(decodedBytes); + } catch (e) { + logger.d(e); + } + } - Future createVideoPlayer() async { + Future createVideoPlayer(String encodedBytes) async { try { - Uint8List decodedBytes = base64Decode(widget.encodedBytes.split("base64,").last); + Uint8List decodedBytes = base64Decode(encodedBytes.split("base64,").last); Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 File file = Io.File("${appDocumentsDirectory.path}/myAdsVideo.mp4"); file.writeAsBytesSync(decodedBytes); @@ -40,55 +72,15 @@ class _ITGAdsScreenState extends State { } } - void checkType(){ - - // getFileTypeDescription(value); - - - } - - String getFileTypeDescription(String value) { - switch (value) { - case ".pdf": - return "application/pdf"; - case ".png": - return "image/png"; - case ".txt": - return "text/plain"; - case ".jpg": - return "image/jpg"; - case ".jpeg": - return "image/jpeg"; - case ".ppt": - return "application/vnd.openxmlformats-officedocument.presentationml.presentation"; - case ".pptx": - return "application/vnd.openxmlformats-officedocument.presentationml.presentation"; - case ".doc": - return "application/vnd.openxmlformats-officedocument.wordprocessingm"; - case ".docx": - return "application/vnd.openxmlformats-officedocument.wordprocessingm"; - case ".xls": - return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - case ".xlsx": - return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - case ".zip": - return "application/octet-stream"; - case ".rar": - return "application/octet-stream"; - default: - return ""; - } - } - @override void initState() { - _futureController = createVideoPlayer(); + checkFileType(); initTimer(); super.initState(); } void initTimer() { - Future.delayed(const Duration(milliseconds: 500), () { + Future.delayed(const Duration(seconds: 5), () { setState(() { skip = true; }); @@ -107,28 +99,34 @@ class _ITGAdsScreenState extends State { return Scaffold( body: Column( children: [ - SizedBox( - height: MediaQuery.of(context).size.height * .3, - child: FutureBuilder( - future: _futureController, - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) { - _controller = snapshot.data as VideoPlayerController; - return AspectRatio( - aspectRatio: _controller.value.aspectRatio, - child: VideoPlayer(_controller), - ); - } else { - return const Center( - child: CircularProgressIndicator(), - ); - } - }, + if (isVideo) + SizedBox( + height: MediaQuery.of(context).size.height * .3, + child: FutureBuilder( + future: _futureController, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) { + _controller = snapshot.data as VideoPlayerController; + return AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: VideoPlayer(_controller), + ); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + ), ), - ), + if (isImage) Image.file(imageFile), if (skip) ElevatedButton( - onPressed: () {}, + onPressed: () async { + // DashboardApiClient().setAdvertisementViewed(widget.addMasterId, widget.advertisement!.advertisementId!).then((value) { + // logger.d(value); + // }); + }, child: const Text("Go To Dashboard"), ) ], From 8018120c6a8fbf81c2fd58dd3aec0395fc0e123e Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 27 Nov 2022 10:37:32 +0300 Subject: [PATCH 11/20] chat structure issues. --- lib/api/chat/chat_provider_model.dart | 2 ++ lib/classes/consts.dart | 4 ++-- lib/ui/chat/call/chat_incoming_call_screen.dart | 2 ++ lib/ui/chat/chat_bubble.dart | 3 ++- lib/ui/chat/chat_detailed_screen.dart | 5 +++++ 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 7a27c1f..16eb97f 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -40,6 +40,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; + // todo: @aamir need to make a separate api client for chat, need to improve code structure. + Future getUserAutoLoginToken(BuildContext cxt) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..646e498 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/ui/chat/call/chat_incoming_call_screen.dart b/lib/ui/chat/call/chat_incoming_call_screen.dart index a0b8247..1b6a5aa 100644 --- a/lib/ui/chat/call/chat_incoming_call_screen.dart +++ b/lib/ui/chat/call/chat_incoming_call_screen.dart @@ -91,6 +91,8 @@ class _IncomingCallState extends State with SingleTickerProviderSt mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceAround, children: const [ + + // todo @aamir, need to use extension mehtods Text( "Aamir Saleem Ahmad", style: TextStyle( diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 1696a49..ce2e7db 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -3,7 +3,8 @@ 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:sizer/sizer.dart'; + +// todo: @aamir use extension methods, and use correct widgets. class ChatBubble extends StatelessWidget { const ChatBubble( diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 4a8e70c..d8a9cbd 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -30,6 +30,8 @@ class ChatDetailScreen extends StatefulWidget { State createState() => _ChatDetailScreenState(); } +// todo: @aamir use extension methods, and use correct widgets. + class _ChatDetailScreenState extends State { dynamic userDetails; late ChatProviderModel data; @@ -194,6 +196,7 @@ class _ChatDetailScreenState extends State { ], ), if (m.isFileSelected && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") + // todo @aamir use correct code Card( margin: EdgeInsets.zero, elevation: 0, @@ -383,6 +386,8 @@ class _ChatDetailScreenState extends State { }; CallDataModel incomingCallData = CallDataModel.fromJson(json); + + // todo @aamir, we are using namedPagedRoute, need to replace await Navigator.push( context, MaterialPageRoute( From fa36cd7ddff49f94bb845abd328e84d064a9fa57 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 27 Nov 2022 12:24:21 +0300 Subject: [PATCH 12/20] Advertisement Image/ Video Module --- lib/classes/consts.dart | 4 +- lib/provider/chat_provider_model.dart | 2 +- lib/ui/landing/dashboard_screen.dart | 66 +++++++++++++-------------- 3 files changed, 36 insertions(+), 36 deletions(-) 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/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 81cb8b5..02bf689 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -241,7 +241,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); - logger.d(items); + // logger.d(items); for (dynamic item in items[0]) { searchedChats!.forEach( (ChatUser element) { diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index c8cdcef..b699455 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -100,39 +100,39 @@ class _DashboardScreenState extends State { Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, - // appBar: AppBar( - // actions: [ - // IconButton( - // onPressed: () { - // data.getITGNotification().then((val) { - // if (val!.result!.data != null) { - // if (val.result!.data!.notificationType == "Survey") { - // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); - // } else { - // DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - // (value) { - // if (value!.mohemmItgResponseItem!.statusCode == 200) { - // if (value.mohemmItgResponseItem!.result!.data != null) { - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (BuildContext context) => ITGAdsScreen( - // addMasterId: val.result!.data!.notificationMasterId!, - // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, - // ), - // ), - // ); - // } - // } - // }, - // ); - // } - // } - // }); - // }, - // icon: Icon(Icons.add)) - // ], - // ), + appBar: AppBar( + actions: [ + IconButton( + onPressed: () { + data.getITGNotification().then((val) { + if (val!.result!.data != null) { + if (val.result!.data!.notificationType == "Survey") { + Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + } else { + DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( + (value) { + if (value!.mohemmItgResponseItem!.statusCode == 200) { + if (value.mohemmItgResponseItem!.result!.data != null) { + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => ITGAdsScreen( + addMasterId: val.result!.data!.notificationMasterId!, + advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, + ), + ), + ); + } + } + }, + ); + } + } + }); + }, + icon: Icon(Icons.add)) + ], + ), body: Column( children: [ Row( From ccb89584e2256cff87a91b726098fccf413f9024 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 27 Nov 2022 12:24:21 +0300 Subject: [PATCH 13/20] chat structure issues. --- lib/classes/colors.dart | 1 + lib/classes/consts.dart | 12 +- lib/ui/chat/chat_bubble.dart | 56 ++++ lib/ui/chat/chat_detailed_screen.dart | 413 ++++++++++---------------- lib/ui/chat/chat_home.dart | 14 +- lib/ui/chat/chat_home_screen.dart | 52 +--- 6 files changed, 231 insertions(+), 317 deletions(-) diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index f99cc31..10681be 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -17,6 +17,7 @@ class MyColors { static const Color greyF7Color = Color(0xffF7F7F7); static const Color grey80Color = Color(0xff808080); static const Color grey70Color = Color(0xff707070); + static const Color grey7BColor = Color(0xff7B7B7B); static const Color greyACColor = Color(0xffACACAC); static const Color grey98Color = Color(0xff989898); static const Color lightGreyEFColor = Color(0xffEFEFEF); diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..4d6eca8 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/"; @@ -10,10 +10,12 @@ class ApiConsts { static String user = baseUrlServices + "api/User/"; static String cocRest = baseUrlServices + "COCWS.svc/REST/"; + // todo @aamir move api end point last repo to concerned method. + //Chat - static String chatServerBaseUrl = "https://apiderichat.hmg.com"; - static String chatServerBaseApiUrl = "https://apiderichat.hmg.com/api/"; - static String chatHubConnectionUrl = chatServerBaseUrl + "/ConnectionChatHub"; + static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; + static String chatServerBaseApiUrl = chatServerBaseUrl + "api/"; + static String chatHubConnectionUrl = chatServerBaseUrl + "ConnectionChatHub"; static String chatSearchMember = "user/getUserWithStatusAndFavAsync/"; static String chatRecentUrl = "UserChatHistory/getchathistorybyuserid"; //For a Mem static String chatSingleUserHistoryUrl = "UserChatHistory/GetUserChatHistory"; diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index a7dd9b0..38c47ae 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -29,6 +29,8 @@ class ChatBubble extends StatelessWidget { @override Widget build(BuildContext context) { + return isCurrentUser ? currentUser(context) : receiptUser(context); + return Padding( // padding: EdgeInsets.zero, padding: EdgeInsets.only( @@ -148,4 +150,58 @@ class ChatBubble extends StatelessWidget { ), ); } + + Widget currentUser(context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (text).toText12(), + Align( + alignment: Alignment.centerRight, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + dateTime.toText10(color: MyColors.grey41Color.withOpacity(.5)), + 7.width, + Icon( + isDelivered ? Icons.done_all : Icons.done_all, + color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, + size: 14, + ), + ], + ), + ), + ], + ).paddingOnly(top: 11, left: 13, right: 7, bottom: 5).objectContainerView(disablePadding: true).paddingOnly(left: MediaQuery.of(context).size.width * 0.3); + } + + Widget receiptUser(context) { + return Container( + padding: const EdgeInsets.only(top: 11, left: 13, right: 7, bottom: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + gradient: const LinearGradient( + transform: GradientRotation(.83), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (text).toText12(color: Colors.white), + Align( + alignment: Alignment.centerRight, + child: dateTime.toText10( + color: Colors.white.withOpacity(.71), + ), + ), + ], + ), + ).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); + } } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index a3cf2e9..00bb43b 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,18 +1,16 @@ import 'dart:async'; -import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:mohem_flutter_app/provider/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/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'; import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; @@ -49,9 +47,7 @@ class _ChatDetailScreenState extends State { } } await Future.delayed( - const Duration( - milliseconds: 1000, - ), + const Duration(milliseconds: 1000), ); _rc.loadComplete(); } @@ -71,283 +67,172 @@ class _ChatDetailScreenState extends State { return Scaffold( backgroundColor: MyColors.backgroundColor, - appBar: AppBarWidget(context, - title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, - showHomeButton: false, - image: userDetails["targetUser"].image, - actions: [ - IconButton( - onPressed: () { - makeCall( - callType: "AUDIO", - con: hubConnection, - ); - }, - icon: SvgPicture.asset( - "assets/icons/chat/call.svg", - width: 22, - height: 22, - ), - ), - IconButton( - onPressed: () { - makeCall( - callType: "VIDEO", - con: hubConnection, - ); - }, - icon: SvgPicture.asset( - "assets/icons/chat/video_call.svg", - width: 20, - height: 20, - ), - ), - 10.width, - ]), + appBar: AppBarWidget( + context, + title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, + showHomeButton: false, + image: userDetails["targetUser"].image, + actions: [ + IconButton( + onPressed: () { + makeCall(callType: "AUDIO", con: hubConnection); + }, + icon: SvgPicture.asset("assets/icons/chat/call.svg", width: 22, height: 22), + ), + IconButton( + onPressed: () { + makeCall(callType: "VIDEO", con: hubConnection); + }, + icon: SvgPicture.asset("assets/icons/chat/video_call.svg", width: 20, height: 20), + ), + 10.width, + ], + ), body: Consumer( builder: (BuildContext context, ChatProviderModel m, Widget? child) { return (m.isLoading ? ChatHomeShimmer() : Column( children: [ - Expanded( - flex: 2, - child: SmartRefresher( - enablePullDown: false, - enablePullUp: true, - onLoading: () { - getMoreChat(); - }, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, - ), - controller: _rc, + 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, - 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], - ); - }, - ); - }, - ), + itemCount: m.userChatHistory.length, + padding: const EdgeInsets.all(21), + separatorBuilder: (cxt, index) => 8.height, + 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], + ); + }, + ); + }, ), - ), + ).expanded, if (m.isMsgReply) - Row( - children: [ - 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, - ), - ), - ), + 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, + const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), + ], ), - ), - ), - ], + ).expanded, + ], + ), ), 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, + SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), + 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), + prefixIconConstraints: BoxConstraints(), + prefixIcon: m.sFileType.isNotEmpty ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover) : null, + suffixIcon: SizedBox( + width: 96, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, // added line + children: [ + if (m.sFileType.isNotEmpty) + IconButton( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + icon: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + 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), + ], ), - fit: BoxFit.cover, - ), - borderRadius: const BorderRadius.all( - Radius.circular(0), + onPressed: () async { + m.removeAttachment(); + }, ), - ), - 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: [ - 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: [ - if (m.sFileType.isNotEmpty) - IconButton( + if (m.sFileType.isEmpty) + RotationTransition( + turns: const AlwaysStoppedAnimation(45 / 360), + child: IconButton( padding: EdgeInsets.zero, - alignment: Alignment.centerRight, - icon: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - 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, - ), - ], - ), + alignment: Alignment.topRight, + icon: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor), onPressed: () async { - m.removeAttachment(); + m.selectImageToUpload(context); }, ), - 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, + ), + 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), ), ), ], diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 3ad9b12..3bf8cda 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -1,19 +1,13 @@ -import 'dart:convert'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:mohem_flutter_app/provider/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'; 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/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/chat_home_screen.dart'; import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; -import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/items_for_sale.dart'; -import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/my_posted_ads_fragment.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; @@ -45,11 +39,7 @@ class _ChatHomeState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: MyColors.white, - appBar: AppBarWidget( - context, - title: LocaleKeys.chat.tr(), - showHomeButton: true, - ), + appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), body: Column( children: [ Container( diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index a6f91b8..db18166 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -2,13 +2,13 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:mohem_flutter_app/provider/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/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/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; @@ -51,50 +51,30 @@ class _ChatHomeScreenState extends State { physics: const AlwaysScrollableScrollPhysics(), children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 20, - horizontal: 20, - ), + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), child: TextField( controller: m.search, + style: const TextStyle(color: MyColors.darkTextColor, fontWeight: FontWeight.w500, fontSize: 12), onChanged: (String val) { m.filter(val); }, decoration: InputDecoration( - border: fieldBorder( - radius: 5, - color: 0xFFE5E5E5, - ), - focusedBorder: fieldBorder( - radius: 5, - color: 0xFFE5E5E5, - ), - enabledBorder: fieldBorder( - radius: 5, - color: 0xFFE5E5E5, - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 15, - vertical: 10, - ), + border: fieldBorder(radius: 5, color: 0xFFE5E5E5), + focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), + enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), + contentPadding: const EdgeInsets.all(11), hintText: LocaleKeys.searchfromchat.tr(), - hintStyle: const TextStyle( - color: MyColors.lightTextColor, - fontStyle: FontStyle.italic, - ), + hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500, fontSize: 12), filled: true, - fillColor: const Color( - 0xFFF7F7F7, - ), + fillColor: const Color(0xFFF7F7F7), + suffixIconConstraints: const BoxConstraints(), suffixIcon: m.search.text.isNotEmpty ? IconButton( + constraints: const BoxConstraints(), onPressed: () { m.clearSelections(); }, - icon: const Icon( - Icons.clear, - size: 22, - ), + icon: const Icon(Icons.clear, size: 22), color: MyColors.redA3Color, ) : null, @@ -103,15 +83,15 @@ class _ChatHomeScreenState extends State { ), if (m.searchedChats != null) ListView.separated( - itemCount: m.searchedChats!.length, - padding: const EdgeInsets.only( - bottom: 80, - ), + itemCount: m.searchedChats!.length + 20, + padding: const EdgeInsets.only(bottom: 80), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { + index = 0; return SizedBox( height: 55, + // todo @aamir, remove list tile, make a custom ui instead child: ListTile( leading: Stack( children: [ From 7f2aa4415d702e38f9f6855e72db20c23300e07a Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 27 Nov 2022 12:25:15 +0300 Subject: [PATCH 14/20] improvement. --- lib/ui/chat/chat_home_screen.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index db18166..56c17d8 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -83,12 +83,11 @@ class _ChatHomeScreenState extends State { ), if (m.searchedChats != null) ListView.separated( - itemCount: m.searchedChats!.length + 20, + itemCount: m.searchedChats!.length, padding: const EdgeInsets.only(bottom: 80), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { - index = 0; return SizedBox( height: 55, // todo @aamir, remove list tile, make a custom ui instead From 545c33ee4afe8fbbe873a420816d002ae8b9946a Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 27 Nov 2022 16:52:18 +0300 Subject: [PATCH 15/20] Chat Fixes --- lib/api/chat/chat_api_client.dart | 16 ++-- lib/classes/consts.dart | 16 ++-- lib/config/routes.dart | 30 +++----- lib/provider/chat_provider_model.dart | 5 +- lib/ui/chat/chat_bubble.dart | 44 +++++++++++ lib/ui/chat/chat_detailed_screen.dart | 75 +++++++------------ lib/ui/chat/chat_home_screen.dart | 1 + lib/ui/landing/dashboard_screen.dart | 71 ++++++++++-------- .../itg/its_add_screen_video_image.dart | 31 ++++---- 9 files changed, 159 insertions(+), 130 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 0d1653d..323c3d4 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -18,7 +18,7 @@ class ChatApiClient { Future getUserLoginToken() async { Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", + "${ApiConsts.chatLoginTokenUrl}externaluserlogin", { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", @@ -32,7 +32,7 @@ class ChatApiClient { Future?> getChatMemberFromSearch(String sName, int cUserId) async { Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId", + "${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync/$sName/$cUserId", token: AppState().chatDetails!.response!.token, ); return searchUserJsonModel(response.body); @@ -44,7 +44,7 @@ class ChatApiClient { Future getRecentChats() async { Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", + "${ApiConsts.chatRecentUrl}getchathistorybyuserid", token: AppState().chatDetails!.response!.token, ); return ChatUserModel.fromJson( @@ -54,7 +54,7 @@ class ChatApiClient { Future getFavUsers() async { Response favRes = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}", + "${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}", token: AppState().chatDetails!.response!.token, ); return ChatUserModel.fromJson( @@ -64,7 +64,7 @@ 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.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", + "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal", token: AppState().chatDetails!.response!.token, ); return response; @@ -72,7 +72,7 @@ class ChatApiClient { Future favUser({required int userID, required int targetUserID}) async { Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", + "${ApiConsts.chatFavUser}addFavUser", { "targetUserId": targetUserID, "userId": userID, @@ -84,7 +84,7 @@ class ChatApiClient { Future unFavUser({required int userID, required int targetUserID}) async { Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}FavUser/deleteFavUser", + "${ApiConsts.chatFavUser}deleteFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token, ); @@ -93,7 +93,7 @@ class ChatApiClient { } Future uploadMedia(String userId, File file) async { - dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}')); + dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}upload')); request.fields.addAll({'userId': userId, 'fileSource': '1'}); request.files.add(await MultipartFile.fromPath('files', file.path)); request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 4d6eca8..edc866f 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 @@ -15,12 +15,14 @@ class ApiConsts { //Chat static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; static String chatServerBaseApiUrl = chatServerBaseUrl + "api/"; + static String chatLoginTokenUrl = chatServerBaseApiUrl + "user/"; static String chatHubConnectionUrl = chatServerBaseUrl + "ConnectionChatHub"; - static String chatSearchMember = "user/getUserWithStatusAndFavAsync/"; - static String chatRecentUrl = "UserChatHistory/getchathistorybyuserid"; //For a Mem - static String chatSingleUserHistoryUrl = "UserChatHistory/GetUserChatHistory"; - static String chatMediaImageUploadUrl = "shared/upload"; - static String chatFavoriteUsers = "FavUser/getFavUserById/"; + + // static String chatSearchMember = chatLoginTokenUrl + "user/"; + static String chatRecentUrl = chatServerBaseApiUrl + "UserChatHistory/"; //For a Mem + static String chatSingleUserHistoryUrl = chatServerBaseApiUrl + "UserChatHistory/"; + static String chatMediaImageUploadUrl = chatServerBaseApiUrl + "shared/"; + static String chatFavUser = chatServerBaseApiUrl + "FavUser/"; } class SharedPrefsConsts { diff --git a/lib/config/routes.dart b/lib/config/routes.dart index ab3fb9a..7cf8a35 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_home.dart'; import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; +import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart'; @@ -87,6 +88,7 @@ class AppRoutes { static const String addEitScreen = "/addeitScreen"; static const String initialRoute = login; static const String survey = "/survey"; + static const String advertisement = "/advertisement"; //Work List static const String workList = "/workList"; @@ -116,8 +118,7 @@ class AppRoutes { static const String addVacationRule = "/addVacationRule"; //Bottom Sheet - static const String attendanceDetailsBottomSheet = - "/attendanceDetailsBottomSheet"; + static const String attendanceDetailsBottomSheet = "/attendanceDetailsBottomSheet"; //Profile static const String profile = "/profile"; @@ -135,8 +136,7 @@ class AppRoutes { // Pending Transactions static const String pendingTransactions = "/pendingTransactions"; - static const String pendingTransactionsDetails = - "/pendingTransactionsDetails"; + static const String pendingTransactionsDetails = "/pendingTransactionsDetails"; // Announcements static const String announcements = "/announcements"; @@ -192,6 +192,7 @@ class AppRoutes { verifyLastLogin: (BuildContext context) => VerifyLastLoginScreen(), dashboard: (BuildContext context) => DashboardScreen(), survey: (BuildContext context) => SurveyScreen(), + advertisement: (BuildContext context) => ITGAdsScreen(), subMenuScreen: (BuildContext context) => SubMenuScreen(), newPassword: (BuildContext context) => NewPasswordScreen(), @@ -223,8 +224,7 @@ class AppRoutes { addVacationRule: (BuildContext context) => AddVacationRuleScreen(), //Bottom Sheet - attendanceDetailsBottomSheet: (BuildContext context) => - AttendenceDetailsBottomSheet(), + attendanceDetailsBottomSheet: (BuildContext context) => AttendenceDetailsBottomSheet(), //Profile //profile: (BuildContext context) => Profile(), @@ -235,13 +235,10 @@ class AppRoutes { familyMembers: (BuildContext context) => FamilyMembers(), dynamicScreen: (BuildContext context) => DynamicListViewScreen(), addDynamicInput: (BuildContext context) => DynamicInputScreen(), - addDynamicInputProfile: (BuildContext context) => - DynamicInputScreenProfile(), - addDynamicAddressScreen: (BuildContext context) => - DynamicInputScreenAddress(), + addDynamicInputProfile: (BuildContext context) => DynamicInputScreenProfile(), + addDynamicAddressScreen: (BuildContext context) => DynamicInputScreenAddress(), - deleteFamilyMember: (BuildContext context) => - DeleteFamilyMember(ModalRoute.of(context)!.settings.arguments as int), + deleteFamilyMember: (BuildContext context) => DeleteFamilyMember(ModalRoute.of(context)!.settings.arguments as int), requestSubmitScreen: (BuildContext context) => RequestSubmitScreen(), addUpdateFamilyMember: (BuildContext context) => AddUpdateFamilyMember(), @@ -251,8 +248,7 @@ class AppRoutes { mowadhafhiHRRequest: (BuildContext context) => MowadhafhiHRRequest(), pendingTransactions: (BuildContext context) => PendingTransactions(), - pendingTransactionsDetails: (BuildContext context) => - PendingTransactionsDetails(), + pendingTransactionsDetails: (BuildContext context) => PendingTransactionsDetails(), announcements: (BuildContext context) => Announcements(), announcementsDetails: (BuildContext context) => AnnouncementDetails(), @@ -268,8 +264,7 @@ class AppRoutes { // Offers & Discounts offersAndDiscounts: (BuildContext context) => OffersAndDiscountsHome(), - offersAndDiscountsDetails: (BuildContext context) => - OffersAndDiscountsDetails(), + offersAndDiscountsDetails: (BuildContext context) => OffersAndDiscountsDetails(), //pay slip monthlyPaySlip: (BuildContext context) => MonthlyPaySlipScreen(), @@ -296,8 +291,7 @@ class AppRoutes { // Marathon marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(), marathonScreen: (BuildContext context) => MarathonScreen(), - marathonWinnerSelection: (BuildContext context) => - MarathonWinnerSelection(), + marathonWinnerSelection: (BuildContext context) => MarathonWinnerSelection(), marathonWinnerScreen: (BuildContext context) => WinnerScreen(), }; } diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 02bf689..dc98858 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -241,7 +241,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); - // logger.d(items); + logger.d(items); for (dynamic item in items[0]) { searchedChats!.forEach( (ChatUser element) { @@ -292,7 +292,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserId = temp.first.targetUserId; data.first.currentUserName = temp.first.targetUserName; } - logger.d(jsonEncode(data)); userChatHistory.insert(0, data.first); var list = [ { @@ -601,6 +600,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void clearSelections() { + print("Hereee i am "); searchedChats = pChatHistory; search.clear(); isChatScreenActive = false; @@ -609,6 +609,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isFileSelected = false; repliedMsg = []; sFileType = ""; + isMsgReply = false; notifyListeners(); } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 38c47ae..bcf78aa 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -155,6 +155,28 @@ class ChatBubble extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + if (isReplied) + ClipRRect( + borderRadius: BorderRadius.circular( + 5.0, + ), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + border: Border( + left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), + ), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + replyText.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4).paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + ], + ).expanded, + ), + ).paddingOnly(right: 5, bottom: 7), (text).toText12(), Align( alignment: Alignment.centerRight, @@ -193,6 +215,28 @@ class ChatBubble extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + if (isReplied) + ClipRRect( + borderRadius: BorderRadius.circular( + 5.0, + ), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + border: Border( + left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), + ), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + replyText.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4).paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + ], + ).expanded, + ), + ).paddingOnly(right: 5, bottom: 7), (text).toText12(color: Colors.white), Align( alignment: Alignment.centerRight, diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 00bb43b..e0f7f93 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -19,6 +19,7 @@ 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:sizer/sizer.dart'; import 'package:swipe_to/swipe_to.dart'; class ChatDetailScreen extends StatefulWidget { @@ -74,14 +75,16 @@ class _ChatDetailScreenState extends State { image: userDetails["targetUser"].image, actions: [ IconButton( + constraints: const BoxConstraints(), onPressed: () { - makeCall(callType: "AUDIO", con: hubConnection); + // 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); + //makeCall(callType: "VIDEO", con: hubConnection); }, icon: SvgPicture.asset("assets/icons/chat/video_call.svg", width: 20, height: 20), ), @@ -176,63 +179,43 @@ class _ChatDetailScreenState extends State { 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), + filled: true, + fillColor: MyColors.white, + contentPadding: EdgeInsets.only( + left: 21, + top: 20, + bottom: 20, + ), prefixIconConstraints: BoxConstraints(), - prefixIcon: m.sFileType.isNotEmpty ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover) : null, + 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, suffixIcon: SizedBox( - width: 96, + width: 100, child: Row( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.center, // added line children: [ if (m.sFileType.isNotEmpty) - IconButton( - padding: EdgeInsets.zero, - alignment: Alignment.centerRight, - icon: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - 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(); - }, - ), + 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: 25), 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); - }, + child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( + () => 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: 25), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( + () => m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName, context), + ), ], ), - ).paddingOnly(right: 20), + ).paddingOnly(right: 21), ), ), ], diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 56c17d8..2724683 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -162,6 +162,7 @@ class _ChatHomeScreenState extends State { ), Flexible( child: IconButton( + constraints: BoxConstraints(), alignment: Alignment.centerRight, padding: EdgeInsets.zero, icon: Icon( diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index b699455..d9b565c 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -100,39 +100,44 @@ class _DashboardScreenState extends State { Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, - appBar: AppBar( - actions: [ - IconButton( - onPressed: () { - data.getITGNotification().then((val) { - if (val!.result!.data != null) { - if (val.result!.data!.notificationType == "Survey") { - Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); - } else { - DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { - if (value!.mohemmItgResponseItem!.statusCode == 200) { - if (value.mohemmItgResponseItem!.result!.data != null) { - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => ITGAdsScreen( - addMasterId: val.result!.data!.notificationMasterId!, - advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, - ), - ), - ); - } - } - }, - ); - } - } - }); - }, - icon: Icon(Icons.add)) - ], - ), + // appBar: AppBar( + // actions: [ + // IconButton( + // onPressed: () { + // data.getITGNotification().then((val) { + // if (val!.result!.data != null) { + // if (val.result!.data!.notificationType == "Survey") { + // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + // } else { + // DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( + // (value) { + // if (value!.mohemmItgResponseItem!.statusCode == 200) { + // if (value.mohemmItgResponseItem!.result!.data != null) { + // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { + // "masterId": val.result!.data!.notificationMasterId, + // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, + // }); + // + // // Navigator.push( + // // context, + // // MaterialPageRoute( + // // builder: (BuildContext context) => ITGAdsScreen( + // // addMasterId: val.result!.data!.notificationMasterId!, + // // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, + // // ), + // // ), + // // ); + // } + // } + // }, + // ); + // } + // } + // }); + // }, + // icon: Icon(Icons.add)) + // ], + // ), body: Column( children: [ Row( diff --git a/lib/ui/landing/itg/its_add_screen_video_image.dart b/lib/ui/landing/itg/its_add_screen_video_image.dart index 4b2e358..a71a71b 100644 --- a/lib/ui/landing/itg/its_add_screen_video_image.dart +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -12,10 +12,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:video_player/video_player.dart'; class ITGAdsScreen extends StatefulWidget { - final String addMasterId; - final ads.Advertisement advertisement; - - const ITGAdsScreen({required this.addMasterId, required this.advertisement}); + const ITGAdsScreen({Key? key}) : super(key: key); @override _ITGAdsScreenState createState() => _ITGAdsScreenState(); @@ -29,10 +26,13 @@ class _ITGAdsScreenState extends State { bool isImage = false; String ext = ''; late File imageFile; + ads.Advertisement? advertisementData; + dynamic data; + String? masterID; void checkFileType() async { - String? rFile = widget.advertisement!.viewAttachFileColl!.first.base64String; - String? rFileExt = widget.advertisement!.viewAttachFileColl!.first.fileName; + String? rFile = advertisementData!.viewAttachFileColl!.first.base64String; + String? rFileExt = advertisementData!.viewAttachFileColl!.first.fileName; ext = "." + rFileExt!.split(".").last.toLowerCase(); if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") { await processImage(rFile!); @@ -42,6 +42,7 @@ class _ITGAdsScreenState extends State { _futureController = createVideoPlayer(rFile!); } setState(() {}); + initTimer(); } Future processImage(String encodedBytes) async { @@ -72,18 +73,10 @@ class _ITGAdsScreenState extends State { } } - @override - void initState() { - checkFileType(); - initTimer(); - super.initState(); - } - void initTimer() { Future.delayed(const Duration(seconds: 5), () { - setState(() { - skip = true; - }); + skip = true; + setState(() {}); }); } @@ -95,6 +88,12 @@ class _ITGAdsScreenState extends State { @override Widget build(BuildContext context) { + data = ModalRoute.of(context)!.settings.arguments; + if (advertisementData == null) advertisementData = data["advertisement"] as ads.Advertisement; + if (masterID == null) masterID = data["masterId"]; + if (advertisementData != null) { + checkFileType(); + } double height = MediaQuery.of(context).size.height * .25; return Scaffold( body: Column( From 967257ec2ec96234ec48124c5d4d1587871bfcf1 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 28 Nov 2022 10:26:15 +0300 Subject: [PATCH 16/20] Chat Fixes --- lib/api/api_client.dart | 115 +++----------- lib/api/chat/chat_api_client.dart | 34 +++- lib/provider/chat_provider_model.dart | 3 + lib/ui/chat/chat_home_screen.dart | 210 ++++++++++--------------- lib/ui/chat/favorite_users_screen.dart | 118 +++++++------- 5 files changed, 189 insertions(+), 291 deletions(-) diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 7a6f668..1e66d45 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -18,8 +18,7 @@ class APIError { APIError(this.errorCode, this.errorMessage); - Map toJson() => - {'errorCode': errorCode, 'errorMessage': errorMessage}; + Map toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage}; @override String toString() { @@ -54,8 +53,7 @@ APIException _throwAPIException(Response response) { return APIException(APIException.INTERNAL_SERVER_ERROR); case 444: var downloadUrl = response.headers["location"]; - return APIException(APIException.UPGRADE_REQUIRED, - arguments: downloadUrl); + return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl); default: return APIException(APIException.OTHER); } @@ -68,13 +66,8 @@ class ApiClient { factory ApiClient() => _instance; - Future postJsonForObject( - FactoryConstructor factoryConstructor, String url, T jsonObject, - {String? token, - Map? queryParameters, - Map? headers, - int retryTimes = 0, - bool isFormData = false}) async { + Future postJsonForObject(FactoryConstructor factoryConstructor, String url, T jsonObject, + {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { var _headers = {'Accept': 'application/json'}; if (headers != null && headers.isNotEmpty) { _headers.addAll(headers); @@ -84,12 +77,7 @@ class ApiClient { var bodyJson = json.encode(jsonObject); print("body:$bodyJson"); } - var response = await postJsonForResponse(url, jsonObject, - token: token, - queryParameters: queryParameters, - headers: _headers, - retryTimes: retryTimes, - isFormData: isFormData); + var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes, isFormData: isFormData); // try { if (!kReleaseMode) { logger.i("res: " + response.body); @@ -102,8 +90,7 @@ class ApiClient { return factoryConstructor(jsonData); } else { APIError? apiError; - apiError = - APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage']); + apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage']); throw APIException(APIException.BAD_REQUEST, error: apiError); } // } catch (ex) { @@ -116,11 +103,7 @@ class ApiClient { } Future postJsonForResponse(String url, T jsonObject, - {String? token, - Map? queryParameters, - Map? headers, - int retryTimes = 0, - bool isFormData = false}) async { + {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { String? requestBody; late Map stringObj; if (jsonObject != null) { @@ -134,22 +117,13 @@ class ApiClient { if (isFormData) { headers = {'Content-Type': 'application/x-www-form-urlencoded'}; - stringObj = ((jsonObject ?? {}) as Map) - .map((key, value) => MapEntry(key, value?.toString() ?? "")); + stringObj = ((jsonObject ?? {}) as Map).map((key, value) => MapEntry(key, value?.toString() ?? "")); } - return await _postForResponse(url, isFormData ? stringObj : requestBody, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes); + return await _postForResponse(url, isFormData ? stringObj : requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); } - Future _postForResponse(String url, requestBody, - {String? token, - Map? queryParameters, - Map? headers, - int retryTimes = 0}) async { + Future _postForResponse(String url, requestBody, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { try { var _headers = {}; if (token != null) { @@ -164,9 +138,7 @@ class ApiClient { var queryString = new Uri(queryParameters: queryParameters).query; url = url + '?' + queryString; } - var response = - await _post(Uri.parse(url), body: requestBody, headers: _headers) - .timeout(Duration(seconds: 120)); + var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120)); if (response.statusCode >= 200 && response.statusCode < 300) { return response; @@ -177,11 +149,7 @@ class ApiClient { if (retryTimes > 0) { print('will retry after 3 seconds...'); await Future.delayed(Duration(seconds: 3)); - return await _postForResponse(url, requestBody, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes - 1); + return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); } @@ -189,11 +157,7 @@ class ApiClient { if (retryTimes > 0) { print('will retry after 3 seconds...'); await Future.delayed(Duration(seconds: 3)); - return await _postForResponse(url, requestBody, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes - 1); + return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); } @@ -203,39 +167,23 @@ class ApiClient { if (retryTimes > 0) { print('will retry after 3 seconds...'); await Future.delayed(Duration(seconds: 3)); - return await _postForResponse(url, requestBody, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes - 1); + return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); } } } - Future getJsonForResponse(String url, - {String? token, - Map? queryParameters, - Map? headers, - int retryTimes = 0}) async { + Future getJsonForResponse(String url, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { if (headers == null) { headers = {'Content-Type': 'application/json'}; } else { headers['Content-Type'] = 'application/json'; } - return await _getForResponse(url, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); } - Future _getForResponse(String url, - {String? token, - Map? queryParameters, - Map? headers, - int retryTimes = 0}) async { + Future _getForResponse(String url, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { try { var _headers = {}; if (token != null) { @@ -250,8 +198,7 @@ class ApiClient { var queryString = new Uri(queryParameters: queryParameters).query; url = url + '?' + queryString; } - var response = await _get(Uri.parse(url), headers: _headers) - .timeout(Duration(seconds: 60)); + var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60)); if (response.statusCode >= 200 && response.statusCode < 300) { return response; @@ -262,11 +209,7 @@ class ApiClient { if (retryTimes > 0) { print('will retry after 3 seconds...'); await Future.delayed(Duration(seconds: 3)); - return await _getForResponse(url, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes - 1); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); } @@ -274,11 +217,7 @@ class ApiClient { if (retryTimes > 0) { print('will retry after 3 seconds...'); await Future.delayed(Duration(seconds: 3)); - return await _getForResponse(url, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes - 1); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); } @@ -288,19 +227,14 @@ class ApiClient { if (retryTimes > 0) { print('will retry after 3 seconds...'); await Future.delayed(Duration(seconds: 3)); - return await _getForResponse(url, - token: token, - queryParameters: queryParameters, - headers: headers, - retryTimes: retryTimes - 1); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); } } } - Future _get(url, {Map? headers}) => - _withClient((client) => client.get(url, headers: headers)); + Future _get(url, {Map? headers}) => _withClient((client) => client.get(url, headers: headers)); bool _certificateCheck(X509Certificate cert, String host, int port) => true; @@ -314,8 +248,5 @@ class ApiClient { } } - Future _post(url, - {Map? headers, body, Encoding? encoding}) => - _withClient((client) => - client.post(url, headers: headers, body: body, encoding: encoding)); + Future _post(url, {Map? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding)); } diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 323c3d4..6355417 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -5,6 +5,9 @@ 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/utils.dart'; +import 'package:mohem_flutter_app/exceptions/api_exception.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as user; import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; @@ -83,13 +86,30 @@ class ChatApiClient { } Future unFavUser({required int userID, required int targetUserID}) async { - Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatFavUser}deleteFavUser", - {"targetUserId": targetUserID, "userId": userID}, - token: AppState().chatDetails!.response!.token, - ); - fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); - return favoriteChatUser; + try { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatFavUser}deleteFavUser", + {"targetUserId": targetUserID, "userId": userID}, + token: AppState().chatDetails!.response!.token, + ); + fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + return favoriteChatUser; + } 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; + unFavUser(userID: userID, targetUserID: targetUserID); + } else { + Utils.showToast( + userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + ); + } + } + throw e; + } } Future uploadMedia(String userId, File file) async { diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index dc98858..655de86 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -10,6 +10,7 @@ import 'package:mohem_flutter_app/api/chat/chat_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/utils.dart'; +import 'package:mohem_flutter_app/exceptions/api_exception.dart'; import 'package:mohem_flutter_app/main.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'; @@ -586,6 +587,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future unFavoriteUser({required int userID, required int targetUserID}) async { fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().unFavUser(userID: userID, targetUserID: targetUserID); + if (favoriteChatUser.response != null) { for (ChatUser user in searchedChats!) { if (user.id == favoriteChatUser.response!.targetUserId!) { @@ -596,6 +598,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { (ChatUser element) => element.id == targetUserID, ); } + notifyListeners(); } diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 2724683..cf6b8d2 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -46,105 +46,87 @@ class _ChatHomeScreenState extends State { builder: (BuildContext context, ChatProviderModel m, Widget? child) { return m.isLoading ? ChatHomeShimmer() - : ListView( - shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), + : Column( children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: TextField( - controller: m.search, - style: const TextStyle(color: MyColors.darkTextColor, fontWeight: FontWeight.w500, fontSize: 12), - onChanged: (String val) { - m.filter(val); - }, - decoration: InputDecoration( - border: fieldBorder(radius: 5, color: 0xFFE5E5E5), - focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), - enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), - contentPadding: const EdgeInsets.all(11), - hintText: LocaleKeys.searchfromchat.tr(), - hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500, fontSize: 12), - filled: true, - fillColor: const Color(0xFFF7F7F7), - suffixIconConstraints: const BoxConstraints(), - suffixIcon: m.search.text.isNotEmpty - ? IconButton( - constraints: const BoxConstraints(), - onPressed: () { - m.clearSelections(); - }, - icon: const Icon(Icons.clear, size: 22), - color: MyColors.redA3Color, - ) - : null, - ), + TextField( + controller: m.search, + style: const TextStyle(color: MyColors.darkTextColor, fontWeight: FontWeight.w500, fontSize: 12), + onChanged: (String val) { + m.filter(val); + }, + decoration: InputDecoration( + border: fieldBorder(radius: 5, color: 0xFFE5E5E5), + focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), + enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), + contentPadding: const EdgeInsets.all(11), + hintText: LocaleKeys.searchfromchat.tr(), + hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500, fontSize: 12), + filled: true, + fillColor: const Color(0xFFF7F7F7), + suffixIconConstraints: const BoxConstraints(), + suffixIcon: m.search.text.isNotEmpty + ? IconButton( + constraints: const BoxConstraints(), + onPressed: () { + m.clearSelections(); + }, + icon: const Icon(Icons.clear, size: 22), + color: MyColors.redA3Color, + ) + : null, ), - ), + ).paddingOnly(top: 20, bottom: 14), if (m.searchedChats != null) ListView.separated( itemCount: m.searchedChats!.length, - padding: const EdgeInsets.only(bottom: 80), shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + physics: const ClampingScrollPhysics(), itemBuilder: (BuildContext context, int index) { + // todo @aamir, remove list tile, make a custom ui instead return SizedBox( height: 55, - // todo @aamir, remove list tile, make a custom ui instead - child: ListTile( - leading: Stack( - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 48, - width: 48, - ), - Positioned( - right: 5, - bottom: 1, - child: Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - borderRadius: const BorderRadius.all( - Radius.circular(10), + child: Row( + children: [ + Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), ), ), - ), - ) - ], - ), - title: (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor), - // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), - trailing: SizedBox( - width: 60, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - // if (m.searchedChats![index].isLoadingCounter!) - // Flexible( - // child: Container( - // padding: EdgeInsets.zero, - // alignment: Alignment.centerRight, - // width: 18, - // height: 18, - // decoration: const BoxDecoration( - // // color: MyColors.redColor, - // borderRadius: BorderRadius.all( - // Radius.circular(20), - // ), - // ), - // child: CircularProgressIndicator(), - // ), - // ), - if (m.searchedChats![index].unreadMessageCount! > 0) - Flexible( - child: Container( - padding: EdgeInsets.zero, - alignment: Alignment.centerRight, + ) + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13), + ], + ).expanded, + SizedBox( + width: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + if (m.searchedChats![index].unreadMessageCount! > 0) + Container( + alignment: Alignment.center, width: 18, height: 18, decoration: const BoxDecoration( @@ -158,18 +140,12 @@ class _ChatHomeScreenState extends State { color: MyColors.white, ) .center, - ), - ), - Flexible( - child: IconButton( - constraints: BoxConstraints(), - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon( - m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == false ? Icons.star_sharp : Icons.star_sharp, - ), + ).paddingOnly(right: 10).center, + Icon( + m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == false ? Icons.star_sharp : Icons.star_sharp, color: m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == true ? MyColors.yellowColor : MyColors.grey35Color, - onPressed: () { + ).onPress( + () { if (m.searchedChats![index].isFav == null || m.searchedChats![index].isFav == false) { m.favoriteUser( userID: AppState().chatDetails!.response!.id!, @@ -187,40 +163,18 @@ class _ChatHomeScreenState extends State { ); } }, - ), - ) - ], + ).center + ], + ), ), - ), - minVerticalPadding: 0, - onTap: () { - 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 Padding( - padding: EdgeInsets.only( - right: 10, - left: 70, - ), - child: Divider( - color: Color( - 0xFFE5E5E5, - ), - ), - ), - ), + separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.lightGreyE5Color).paddingOnly(left: 59), + ).paddingOnly(bottom: 70).expanded, ], - ); + ).paddingOnly(left: 21, right: 21); }, ), floatingActionButton: FloatingActionButton( diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 8f303cd..88c8f9a 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -26,81 +27,70 @@ class ChatFavoriteUsersScreen extends StatelessWidget { return m.favUsersList != null && m.favUsersList.isNotEmpty ? ListView.separated( itemCount: m.favUsersList!.length, - padding: const EdgeInsets.only(top: 20), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { return SizedBox( height: 55, - child: ListTile( - leading: Stack( - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 48, - width: 48, - ), - Positioned( - right: 5, - bottom: 1, - child: Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: m.favUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - borderRadius: const BorderRadius.all( - Radius.circular(10), + child: Row( + children: [ + Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.favUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), ), ), - ), - ) - ], - ), - title: (m.favUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14( - color: MyColors.darkTextColor, - ), - trailing: IconButton( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon( - m.favUsersList![index].isFav! ? Icons.star : Icons.star_border, + ) + ], ), - color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, - onPressed: () { - if (m.favUsersList![index].isFav!) - m.unFavoriteUser( - userID: AppState().chatDetails!.response!.id!, - targetUserID: m.favUsersList![index].id!, - ); - }, - ), - minVerticalPadding: 0, - onTap: () { - Navigator.pushNamed( - context, - AppRoutes.chatDetailed, - arguments: {"targetUser": m.favUsersList![index], "isNewChat": false}, - ).then( - (Object? value) { - m.clearSelections(); - }, - ); - }, + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (m.favUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13), + ], + ).expanded, + SizedBox( + width: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + Icon( + m.favUsersList![index].isFav! ? Icons.star : Icons.star_border, + color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + ).onPress(() { + if (m.favUsersList![index].isFav!) { + m.unFavoriteUser( + userID: AppState().chatDetails!.response!.id!, + targetUserID: m.favUsersList![index].id!, + ); + } + }).center, + ], + ), + ), + ], ), ); }, - separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only( - right: 10, - left: 70, - ), - child: Divider( - color: Color( - 0xFFE5E5E5, - ), - ), - ), - ) + separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.lightGreyE5Color).paddingOnly(left: 70), + ).paddingAll(21) : Column( children: [ Utils.getNoDataWidget(context).expanded, From 0538a3c313f006697483f1a1feb7063e41a8b00f Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 28 Nov 2022 15:59:15 +0300 Subject: [PATCH 17/20] 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) From 04f5847af9a2d2ee6d312c404b9361180f394437 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 28 Nov 2022 16:01:44 +0300 Subject: [PATCH 18/20] Chat Fixes & Chat Media Preview Api Implementation --- lib/provider/chat_provider_model.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index e08562e..8184d28 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -283,8 +283,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future onMsgReceived(List? parameters) async { - print("--------------------------------RMSG-----------------------------"); - logger.d(parameters); List data = []; List temp = []; for (dynamic msg in parameters!) { From 46af0c42c7c3c77cdc47b5f8d0c0d2b44712f8a5 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 28 Nov 2022 16:14:41 +0300 Subject: [PATCH 19/20] updates & fixes --- lib/classes/date_uitl.dart | 2 +- lib/provider/chat_provider_model.dart | 1 + lib/ui/chat/chat_home_screen.dart | 1 + lib/ui/work_list/worklist_fragments/actions_fragment.dart | 6 +++--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/classes/date_uitl.dart b/lib/classes/date_uitl.dart index f7b8192..f8d1c02 100644 --- a/lib/classes/date_uitl.dart +++ b/lib/classes/date_uitl.dart @@ -20,7 +20,7 @@ class DateUtil { } static DateTime convertSimpleStringDateToDate(String date) { - return DateFormat("MM/dd/yyyy hh:mm:ss").parse(date); + return DateFormat("MM/dd/yyyy hh:mm:ss a").parse(date); } static DateTime convertSimpleStringDateToDateddMMyyyy(String date) { diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index dc98858..74ee633 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -435,6 +435,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ChatUser( id: targetUserId, userName: targetUserName, + unreadMessageCount: 0 ), ); notifyListeners(); diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 2724683..95ff2ed 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -47,6 +47,7 @@ class _ChatHomeScreenState extends State { return m.isLoading ? ChatHomeShimmer() : ListView( + padding: EdgeInsets.zero, shrinkWrap: true, physics: const AlwaysScrollableScrollPhysics(), children: [ diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index fa29d65..98b5b72 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -147,15 +147,15 @@ class ActionsFragment extends StatelessWidget { if (actionHistoryList[index].aCTIONCODE == "SUBMIT") { return ""; } else if (actionHistoryList[index].aCTIONCODE == "PENDING") { - if (actionHistoryList[++index].nOTIFICATIONDATE!.isEmpty) { + if (actionHistoryList[index + 1].nOTIFICATIONDATE!.isEmpty) { return ""; } - DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[++index].nOTIFICATIONDATE!); + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index + 1].nOTIFICATIONDATE!); Duration duration = DateTime.now().difference(dateTimeFrom); return "Action duration: " + DateUtil.formatDuration(duration); } else { DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index].nOTIFICATIONDATE!); - DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[++index].nOTIFICATIONDATE!); + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index + 1].nOTIFICATIONDATE!); Duration duration = dateTimeTo.difference(dateTimeFrom); return "Action duration: " + DateUtil.formatDuration(duration); } From 7d651c247af652d992bee0794f038ace133e76e5 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 29 Nov 2022 15:47:32 +0300 Subject: [PATCH 20/20] marathon improvements. --- lib/classes/consts.dart | 4 +- lib/extensions/string_extensions.dart | 7 +- lib/ui/landing/dashboard_screen.dart | 2 +- lib/ui/marathon/marathon_intro_screen.dart | 151 ++++++------------ lib/ui/marathon/marathon_provider.dart | 2 +- lib/ui/marathon/marathon_screen.dart | 69 ++++---- .../marathon/marathon_winner_selection.dart | 26 +-- lib/ui/marathon/widgets/countdown_timer.dart | 2 + lib/ui/marathon/widgets/marathon_banner.dart | 3 +- lib/ui/marathon/widgets/question_card.dart | 81 ++++------ pubspec.yaml | 4 - 11 files changed, 151 insertions(+), 200 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 4d6eca8..46e9f8e 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/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 8bc15e7..3546f6b 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -136,7 +136,7 @@ extension EmailValidator on String { Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text( this, maxLines: maxlines, - style: TextStyle(color: color ?? MyColors.grey3AColor, fontSize: 21, letterSpacing: -0.31, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600)), + style: TextStyle(color: color ?? MyColors.grey3AColor, fontSize: 21, letterSpacing: -0.84, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600)), ); Widget toText22({Color? color, bool isBold = false}) => Text( @@ -149,6 +149,11 @@ extension EmailValidator on String { style: TextStyle(height: 23 / 24, color: color ?? MyColors.darkTextColor, fontSize: 24, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); + Widget toText30({Color? color, bool isBold = false}) => Text( + this, + style: TextStyle(height: 20 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.2, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + ); + Widget toText32({Color? color, bool isBold = false}) => Text( this, style: TextStyle(height: 32 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.92, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index c8cdcef..d715337 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -313,7 +313,7 @@ class _DashboardScreenState extends State { ), ], ).paddingOnly(left: 21, right: 21, top: 7), - const MarathonBanner().paddingAll(20), + const MarathonBanner().paddingAll(21), ServicesWidget(), // 8.height, Container( diff --git a/lib/ui/marathon/marathon_intro_screen.dart b/lib/ui/marathon/marathon_intro_screen.dart index f836229..a6ec296 100644 --- a/lib/ui/marathon/marathon_intro_screen.dart +++ b/lib/ui/marathon/marathon_intro_screen.dart @@ -25,26 +25,18 @@ class MarathonIntroScreen extends StatelessWidget { MarathonProvider provider = context.watch(); return Scaffold( appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), - body: Stack( + body: Column( children: [ - SingleChildScrollView( - child: Column( - children: [ - MarathonDetailsCard(provider: provider).paddingAll(15), - MarathonTimerCard( - provider: provider, - timeToMarathon: dummyEndTime, - ).paddingOnly(left: 15, right: 15, bottom: 15), - const SizedBox( - height: 100, - ), - ], - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: MarathonFooter(provider: provider), - ), + ListView( + padding: const EdgeInsets.all(21), + children: [ + MarathonDetailsCard(provider: provider), + 10.height, + MarathonTimerCard(provider: provider, timeToMarathon: dummyEndTime), + ], + ).expanded, + 1.divider, + MarathonFooter(provider: provider), ], ), ); @@ -61,52 +53,41 @@ class MarathonDetailsCard extends StatelessWidget { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 14), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color), - "Saudi Arabia".toText20(color: MyColors.textMixColor, isBold: true), - Row( - children: [ - Flexible( - child: "Nam suscipit turpis in pharetra euismsdef. Duis rutrum at nulla id aliquam".toText14(color: MyColors.grey77Color), - ) - ], - ), - if (provider.itsMarathonTime) ...[ - 5.height, - Row( - children: [ - LocaleKeys.prize.tr().toText16(color: MyColors.grey77Color, isBold: true), - " LED 55\" Android TV".toText16(color: MyColors.greenColor, isBold: true), - ], - ), - Row( - children: [ - LocaleKeys.sponsoredBy.tr().toText16(color: MyColors.grey77Color), - " Extra".toText16(color: MyColors.darkTextColor, isBold: true), - ], - ), - 10.height, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - "assets/images/logos/main_mohemm_logo.png", - height: 40, - fit: BoxFit.fill, - width: 150, - ) - ], - ), - ] - ], - ), + LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey57Color), + "Saudi Arabia".toText20(color: MyColors.textMixColor), + "Nam suscipit turpis in pharetra euismsdef. Duis rutrum at nulla id aliquam".toText14(color: MyColors.grey57Color, weight: FontWeight.w500), + if (provider.itsMarathonTime) ...[ + 5.height, + Row( + children: [ + LocaleKeys.prize.tr().toText16(color: MyColors.grey57Color), + " LED 55\" Android TV".toText16(color: MyColors.greenColor, isBold: true), + ], + ), + Row( + children: [ + LocaleKeys.sponsoredBy.tr().toText16(color: MyColors.grey57Color), + " Extra".toText16(color: MyColors.darkTextColor), + ], + ), + 10.height, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + "assets/images/logos/main_mohemm_logo.png", + height: 40, + fit: BoxFit.fill, + width: 150, + ) + ], + ), + ] ], ), ); @@ -128,30 +109,23 @@ class MarathonTimerCard extends StatelessWidget { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 14), child: Column( children: [ Row( children: [ - LocaleKeys.gameDate.tr().toText16(color: MyColors.grey77Color), - " 10 Oct, 2022".toText16(color: MyColors.darkTextColor, isBold: true), + LocaleKeys.gameDate.tr().toText16(color: MyColors.grey57Color), + " 10 Oct, 2022".toText16(color: MyColors.darkTextColor), ], ), Row( children: [ - LocaleKeys.gameTime.tr().toText16(color: MyColors.grey77Color), - " 3:00pm".toText16(color: MyColors.darkTextColor, isBold: true), + LocaleKeys.gameTime.tr().toText16(color: MyColors.grey57Color), + " 3:00 pm".toText16(color: MyColors.darkTextColor), ], ), - Lottie.asset( - MyLottieConsts.hourGlassLottie, - height: 200, - ), - BuildCountdownTimer( - timeToMarathon: timeToMarathon, - provider: provider, - screenFlag: 1, - ), + Lottie.asset(MyLottieConsts.hourGlassLottie, height: 200), + BuildCountdownTimer(timeToMarathon: timeToMarathon, provider: provider, screenFlag: 1), ], ), ); @@ -172,38 +146,19 @@ class MarathonFooter extends StatelessWidget { children: [ TextSpan( text: LocaleKeys.note.tr(), - style: const TextStyle( - color: MyColors.darkTextColor, - fontSize: 17, - letterSpacing: -0.64, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.bold), ), TextSpan( text: " " + LocaleKeys.demoMarathonNoteP1.tr(), - style: const TextStyle( - color: MyColors.grey77Color, - fontSize: 17, - letterSpacing: -0.64, - fontWeight: FontWeight.w500, - ), + style: const TextStyle(color: MyColors.grey77Color, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.w500), ), TextSpan( text: " " + LocaleKeys.demoMarathonNoteP2.tr(), - style: const TextStyle( - color: MyColors.darkTextColor, - fontSize: 17, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: MyColors.darkTextColor, fontSize: 17, fontWeight: FontWeight.bold), ), TextSpan( text: " " + LocaleKeys.demoMarathonNoteP3.tr(), - style: const TextStyle( - color: MyColors.grey77Color, - fontSize: 17, - letterSpacing: -0.64, - fontWeight: FontWeight.w500, - ), + style: const TextStyle(color: MyColors.grey77Color, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.w500), ) ], ), diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 5a03b74..46fa74d 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -60,7 +60,7 @@ class MarathonProvider extends ChangeNotifier { oneSec, (Timer timer) async { if (start == 0) { - if (currentQuestionNumber == 9) { + if (currentQuestionNumber == totalQuestions) { timer.cancel(); cancelTimer(); isMarathonCompleted = true; diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index a02733f..5f3e0d8 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -16,8 +16,6 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/custom_status_widget.dart' import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; -import 'package:sizer/sizer.dart'; -import 'package:steps_indicator/steps_indicator.dart'; class MarathonScreen extends StatelessWidget { const MarathonScreen({Key? key}) : super(key: key); @@ -100,7 +98,7 @@ class _MarathonProgressContainerState extends State { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.all(21), + padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 13), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -108,10 +106,7 @@ class _MarathonProgressContainerState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( - decoration: BoxDecoration( - color: MyColors.greenColor, - borderRadius: BorderRadius.circular(5), - ), + decoration: BoxDecoration(color: MyColors.greenColor, borderRadius: BorderRadius.circular(5)), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), child: "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.totalQuestions.toString()} ${LocaleKeys.question.tr()}".toText12(color: MyColors.white), ), @@ -119,36 +114,50 @@ class _MarathonProgressContainerState extends State { "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(), ], ), - 15.height, - StepsIndicator( - lineLength: SizerUtil.deviceType == DeviceType.tablet ? MediaQuery.of(context).size.width * 0.077 : MediaQuery.of(context).size.width * 0.054, - nbSteps: 10, - selectedStep: widget.provider.currentQuestionNumber, - doneLineColor: MyColors.greenColor, - doneStepColor: MyColors.greenColor, - doneLineThickness: 6, - undoneLineThickness: 6, - selectedStepSize: 10, - unselectedStepSize: 10, - doneStepSize: 10, - selectedStepBorderSize: 0, - unselectedStepBorderSize: 0, - selectedStepColorIn: MyColors.greenColor, - selectedStepColorOut: MyColors.greenColor, - unselectedStepColorIn: MyColors.lightGreyDeColor, - unselectedStepColorOut: MyColors.lightGreyDeColor, - undoneLineColor: MyColors.lightGreyDeColor, - enableLineAnimation: false, - enableStepAnimation: false, - ), 12.height, + stepper(widget.provider.currentQuestionNumber), + 8.height, Row( children: [ - "${widget.provider.currentQuestionNumber * 10}% ${LocaleKeys.completed.tr()}".toText14(isBold: true), + "${widget.provider.currentQuestionNumber * 10}% ${LocaleKeys.completed.tr()}".toText14(), ], ), ], ), ); } + + Widget stepper(int value) { + return SizedBox( + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + for (int i = 0; i < 10; i++) + if (value <= i) roundContainer(MyColors.lightGreyDeColor, i != 0) else roundContainer(MyColors.greenColor, i != 0) + ], + ), + ); + } + + Widget roundContainer(Color color, bool isNeedLeftBorder) { + if (isNeedLeftBorder) { + return Row( + children: [ + Divider(thickness: 6, color: color).expanded, + Container( + width: 10, + height: 10, + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + ), + ], + ).expanded; + } + + return Container( + width: 10, + height: 10, + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + ); + } } diff --git a/lib/ui/marathon/marathon_winner_selection.dart b/lib/ui/marathon/marathon_winner_selection.dart index 8462ab4..a5f4e8a 100644 --- a/lib/ui/marathon/marathon_winner_selection.dart +++ b/lib/ui/marathon/marathon_winner_selection.dart @@ -29,7 +29,7 @@ class MarathonWinnerSelection extends StatelessWidget { children: [ 20.height, QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21), - 20.height, + 12.height, InkWell( onTap: () { Navigator.pushNamed(context, AppRoutes.marathonWinnerScreen); @@ -52,8 +52,8 @@ class MarathonWinnerSelection extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "Muhammad Shrouff".toText18(isBold: true, color: MyColors.white), - "837436".toText18(isBold: true, color: MyColors.white), + "Muhammad Shrouff".toText17(isBold: true, color: MyColors.white), + "837436".toText17(isBold: true, color: MyColors.white), ], ), ), @@ -67,10 +67,10 @@ class MarathonWinnerSelection extends StatelessWidget { title: Text( LocaleKeys.fingersCrossed.tr(), style: const TextStyle( - height: 23 / 24, + height: 27 / 27, color: MyColors.greenColor, fontSize: 27, - letterSpacing: -1, + letterSpacing: -1.08, fontWeight: FontWeight.w600, ), ), @@ -78,9 +78,9 @@ class MarathonWinnerSelection extends StatelessWidget { LocaleKeys.winnerSelectedRandomly.tr(), textAlign: TextAlign.center, style: const TextStyle( - color: MyColors.grey77Color, - fontSize: 16, - letterSpacing: -0.64, + color: MyColors.darkTextColor, + fontSize: 18, + letterSpacing: -0.72, fontWeight: FontWeight.w600, ), )).paddingOnly(left: 21, right: 21, top: 20, bottom: 20), @@ -124,22 +124,22 @@ class _QualifiersContainerState extends State { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20), + padding: const EdgeInsets.only(top: 14,left: 18,right: 14,bottom: 18), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - LocaleKeys.winnerSelection.tr().toText18(isBold: true, color: MyColors.grey3AColor), - "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(isBold: true, color: MyColors.redColor), + LocaleKeys.winnerSelection.tr().toText21(color: MyColors.grey3AColor), + "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(color: MyColors.redColor), ], ), 10.height, Row( children: [ - "18 ".toText32(color: MyColors.greenColor), - LocaleKeys.qualifiers.tr().toText20(color: MyColors.greenColor), + "18".toText30(color: MyColors.greenColor, isBold: true),2.width, + LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor), ], ), ], diff --git a/lib/ui/marathon/widgets/countdown_timer.dart b/lib/ui/marathon/widgets/countdown_timer.dart index 6ab8dba..bb8da6d 100644 --- a/lib/ui/marathon/widgets/countdown_timer.dart +++ b/lib/ui/marathon/widgets/countdown_timer.dart @@ -60,6 +60,7 @@ class BuildCountdownTimer extends StatelessWidget { children: [ Column( children: [ + // todo @faiz: Make a separate method and pass string , so we can minimize code replication AutoSizeText( "00", maxFontSize: 24, @@ -155,6 +156,7 @@ class BuildCountdownTimer extends StatelessWidget { children: [ Column( children: [ + // todo @faiz: Make a separate method and pass value and string , so we can minimize code replication time.days == null ? AutoSizeText( "00", diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 55ff715..e90f545 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -1,3 +1,5 @@ +import 'dart:math' as math; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -13,7 +15,6 @@ import 'package:mohem_flutter_app/ui/marathon/marathon_intro_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; import 'package:provider/provider.dart'; -import 'dart:math' as math; class MarathonBanner extends StatelessWidget { const MarathonBanner({Key? key}) : super(key: key); diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index a3fe720..56f1667 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -84,57 +84,39 @@ class CardContent extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: CupertinoColors.white, - boxShadow: [ - BoxShadow( - color: CupertinoColors.systemGrey.withOpacity(0.2), - spreadRadius: 3, - blurRadius: 7, - offset: const Offset(0, 3), - ) - ], - ), - alignment: Alignment.center, - child: Column( - children: [ - Container( - height: 78, - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - transform: GradientRotation(.83), - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ], - ), - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(10), - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 78, + width: double.infinity, + decoration: const BoxDecoration( + gradient: LinearGradient( + transform: GradientRotation(.83), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], ), - child: const Center( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 13), - child: Text( - "What is the capital of Saudi Arabia?", - style: TextStyle( - color: MyColors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), + topRight: Radius.circular(10), ), ), - AnswerContent(question: question, provider: provider), - ], - ), + padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 17), + child: Text( + "What is the capital of Saudi Arabia?", + style: TextStyle( + color: MyColors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + AnswerContent(question: question, provider: provider), + ], ); } } @@ -174,7 +156,7 @@ class _AnswerContentState extends State { @override Widget build(BuildContext context) { return Container( - padding: const EdgeInsets.all(13), + padding: const EdgeInsets.symmetric(vertical: 31, horizontal: 13), decoration: const BoxDecoration( color: MyColors.kWhiteColor, borderRadius: BorderRadius.only( @@ -187,6 +169,7 @@ class _AnswerContentState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + // todo @faiz: Make a separate method and pass value and string , so we can minimize code duplication InkWell( onTap: () { if (widget.provider.currentQuestionNumber == 9) { diff --git a/pubspec.yaml b/pubspec.yaml index f5742bb..fdbdfc8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,14 +79,10 @@ dependencies: pull_to_refresh: ^2.0.0 # lottie json animations lottie: any -# Steps Progress - steps_indicator: ^1.3.0 # Marathon Card Swipe appinio_swiper: ^1.1.1 expandable: ^5.0.1 - - #Chat signalr_netcore: ^1.3.3 logging: ^1.0.1