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 new file mode 100644 index 0000000..91b622a --- /dev/null +++ b/lib/api/chat/chat_api_client.dart @@ -0,0 +1,182 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +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; + +class ChatApiClient { + static final ChatApiClient _instance = ChatApiClient._internal(); + + ChatApiClient._internal(); + + factory ChatApiClient() => _instance; + + Future getUserLoginToken() async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatLoginTokenUrl}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.chatLoginTokenUrl}getUserWithStatusAndFavAsync/$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 { + 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 { + Response favRes = await ApiClient().getJsonForResponse( + "${ApiConsts.chatFavUser}getFavUserById/${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 { + 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 { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatFavUser}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 { + 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 { + 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}'}); + 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 9747e5c..e30af91 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -182,8 +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); +// } } 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 5844822..bdeeecd 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -12,29 +12,20 @@ class ApiConsts { static String user = baseUrlServices + "api/User/"; static String cocRest = baseUrlServices + "COCWS.svc/REST/"; - //Chat - static String chatServerBaseUrl = "https://apiderichat.hmg.com"; - static String chatServerBaseApiUrl = "https://apiderichat.hmg.com/api/"; - 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/"; - -// 42062 is CurrentUserID and 36745 is targetUserID and 0 is For Pagination -// static String chatSearchMember = "https://apiderichat.hmg.com/api/user/getUserWithStatusAndFavAsync/aamir.muhammad/36239"; + // todo @aamir move api end point last repo to concerned method. - //Brain Marathon Constants - static String marathonBaseUrl = "https://18.188.181.12/service/"; - static String marathonParticipantLoginUrl = marathonBaseUrl + "api/auth/participantlogin"; - static String marathonProjectGetUrl = marathonBaseUrl + "api/Project/Project_Get"; - static String marathonUpcomingUrl = marathonBaseUrl + "api/marathon/upcoming/"; - static String marathonHubConnectionUrl = marathonBaseUrl + "MarathonBroadCast"; - - //DummyCards for the UI + //Chat + static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; + static String chatServerBaseApiUrl = chatServerBaseUrl + "api/"; + static String chatLoginTokenUrl = chatServerBaseApiUrl + "user/"; + static String chatHubConnectionUrl = chatServerBaseUrl + "ConnectionChatHub"; - static CardContent dummyQuestion = const CardContent(); + // 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/"; + static String chatUserImages = chatServerBaseUrl + "empservice/api/employee/"; } class SharedPrefsConsts { diff --git a/lib/classes/date_uitl.dart b/lib/classes/date_uitl.dart index a1e52d9..f37fbea 100644 --- a/lib/classes/date_uitl.dart +++ b/lib/classes/date_uitl.dart @@ -40,7 +40,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/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/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/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/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/api/chat/chat_provider_model.dart b/lib/provider/chat_provider_model.dart similarity index 70% rename from lib/api/chat/chat_provider_model.dart rename to lib/provider/chat_provider_model.dart index 7a27c1f..31106c1 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1,21 +1,22 @@ 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/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'; 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 +27,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 +38,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,21 +70,20 @@ 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; + await invokeUserChatHistoryNotDeliveredAsync( + userId: int.parse( + AppState().chatDetails!.response!.id.toString(), + ), + ); notifyListeners(); } - Future getUserChatHistoryNotDeliveredAsync({required int userId}) async { - await hubConnection.invoke( - "GetUserChatHistoryNotDeliveredAsync", - args: [userId], - ); + Future invokeUserChatHistoryNotDeliveredAsync({required int userId}) async { + await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); return ""; } @@ -131,9 +92,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) { @@ -156,9 +119,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ).reversed.toList(); } } - await getUserChatHistoryNotDeliveredAsync( - userId: senderUID, - ); isLoading = false; notifyListeners(); markRead( @@ -173,24 +133,28 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatCID = uuid.v4(); } - 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, + 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); } - ]; - 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(); + } } } } @@ -208,27 +172,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(), @@ -237,59 +184,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(); - getUserChatHistoryNotDeliveredAsync( - userId: int.parse( - AppState().chatDetails!.response!.id.toString(), - ), - ); - 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]) { @@ -342,32 +242,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); + logger.d(items); 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(); } 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"]; @@ -403,13 +294,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserName = temp.first.targetUserName; } 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, @@ -419,14 +303,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?; @@ -556,12 +436,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ChatUser( id: targetUserId, userName: targetUserName, + unreadMessageCount: 0 ), ); notifyListeners(); } if (!isFileSelected && !isMsgReply) { - logger.d("Normal Text Message"); if (message.text == null || message.text.isEmpty) { return; } @@ -569,14 +449,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; } @@ -584,7 +462,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); @@ -697,9 +574,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!) { @@ -712,21 +587,24 @@ 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(); } void clearSelections() { + print("Hereee i am "); searchedChats = pChatHistory; search.clear(); isChatScreenActive = false; @@ -735,6 +613,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isFileSelected = false; repliedMsg = []; sFileType = ""; + isMsgReply = false; notifyListeners(); } @@ -773,4 +652,26 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { curve: Curves.easeIn, ); } + + // 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]); +// } finally { +// hubConnection.off("GetUserChatHistoryNotDeliveredAsync", method: chatNotDelivered); +// } +// } + + + + + + + + + } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 948e5b4..59b62b6 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -1,13 +1,17 @@ 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/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'; 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'; @@ -21,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 @@ -37,6 +42,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Chat bool isChatCounterLoding = true; + bool isChatHubLoding = true; int chatUConvCounter = 0; //Misssing Swipe @@ -97,6 +103,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { leaveBalanceAccrual = null; isChatCounterLoding = true; + isChatHubLoding = true; chatUConvCounter = 0; ticketBalance = 0; @@ -287,6 +294,26 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + Future getUserAutoLoginToken() async { + UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + if (userLoginResponse.response != null) { + AppState().setchatUserDetails = userLoginResponse; + } else { + Utils.showToast( + userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + ); + } + } + + 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/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, 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..8382585 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -1,9 +1,15 @@ +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:sizer/sizer.dart'; +import 'package:mohem_flutter_app/main.dart'; + +// todo: @aamir use extension methods, and use correct widgets. class ChatBubble extends StatelessWidget { const ChatBubble( @@ -15,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; @@ -25,9 +33,13 @@ class ChatBubble extends StatelessWidget { final String dateTime; final bool isReplied; final String userName; + final int? fileTypeID; + final String? fileTypeDescription; @override Widget build(BuildContext context) { + return isCurrentUser ? currentUser(context) : receiptUser(context); + return Padding( // padding: EdgeInsets.zero, padding: EdgeInsets.only( @@ -132,12 +144,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, + ), ], ), ], @@ -147,4 +159,125 @@ class ChatBubble extends StatelessWidget { ), ); } + + Widget currentUser(context) { + 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), + 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( + 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: [ + 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), + if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3) showImage().paddingOnly(right: 5) else (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); + } + + 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 4a8e70c..4dc7c35 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -4,7 +4,6 @@ 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/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -13,13 +12,16 @@ 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'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; +import 'package:sizer/sizer.dart'; import 'package:swipe_to/swipe_to.dart'; class ChatDetailScreen extends StatefulWidget { @@ -38,18 +40,17 @@ 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( - milliseconds: 1000, - ), + const Duration(milliseconds: 1000), ); _rc.loadComplete(); } @@ -68,284 +69,152 @@ class _ChatDetailScreenState extends State { } return Scaffold( - backgroundColor: const Color(0xFFF8F8F8), - appBar: AppBarWidget(context, - title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, - showHomeButton: false, - image: userDetails["targetUser"].image, - actions: [ - IconButton( - onPressed: () { - // makeCall( - // callType: "AUDIO", - // con: data.hubConnection, - // ); - }, - icon: SvgPicture.asset( - "assets/icons/chat/call.svg", - width: 22, - height: 22, - ), - ), - IconButton( - onPressed: () { - // makeCall( - // callType: "VIDEO", - // con: data.hubConnection, - // ); - }, - icon: SvgPicture.asset( - "assets/icons/chat/video_call.svg", - width: 20, - height: 20, - ), - ), - 10.width, - ]), + backgroundColor: MyColors.backgroundColor, + appBar: AppBarWidget( + context, + title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, + showHomeButton: false, + image: userDetails["targetUser"].image, + actions: [ + SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { + // makeCall(callType: "AUDIO", con: hubConnection); + }), + 24.width, + SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() { + // makeCall(callType: "VIDEO", con: hubConnection); + }), + 21.width, + ], + ), body: 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(), + 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, 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, - ), - fit: BoxFit.cover, - ), - borderRadius: const BorderRadius.all( - Radius.circular(0), - ), - ), - child: const SizedBox( - width: double.infinity, - height: 200, - ), - ), - ), + 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, + filled: true, + fillColor: MyColors.white, + contentPadding: const EdgeInsets.only( + left: 21, + top: 20, + bottom: 20, ), - ), - 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, + 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, + suffixIcon: SizedBox( + width: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, // added line + children: [ + if (m.sFileType.isNotEmpty) + Row( children: [ - SvgPicture.asset( - m.getType(m.sFileType), - height: 30, - width: 25, - alignment: Alignment.center, - fit: BoxFit.cover, - ).paddingOnly(left: 20), + const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), + ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), ], - ) - : 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, - ), - ], - ), - onPressed: () async { - m.removeAttachment(); - }, - ), - if (m.sFileType.isEmpty) - RotationTransition( - turns: const AlwaysStoppedAnimation(45 / 360), - child: IconButton( - padding: EdgeInsets.zero, - alignment: Alignment.topRight, - icon: const Icon( - Icons.attach_file_rounded, - size: 26, - color: MyColors.grey3AColor, - ), - onPressed: () async { - m.selectImageToUpload(context); - }, - ), + ).onPress(() => m.removeAttachment()).paddingOnly(right: 25), + if (m.sFileType.isEmpty) + RotationTransition( + turns: const AlwaysStoppedAnimation(45 / 360), + child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( + () => m.selectImageToUpload(context), ), - 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, + ).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: 21), ), ), ], @@ -357,38 +226,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.dart b/lib/ui/chat/chat_home.dart index b2db98a..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/api/chat/chat_provider_model.dart'; -import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; 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'; @@ -31,32 +25,21 @@ 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 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 816aaec..9072b33 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/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/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'; @@ -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() { @@ -36,110 +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, - 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, - ), - hintText: LocaleKeys.searchfromchat.tr(), - hintStyle: const TextStyle( - color: MyColors.lightTextColor, - fontStyle: FontStyle.italic, - ), - filled: true, - fillColor: const Color( - 0xFFF7F7F7, - ), - suffixIcon: m.search.text.isNotEmpty - ? IconButton( - 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, - 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].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( @@ -153,17 +140,12 @@ class _ChatHomeScreenState extends State { color: MyColors.white, ) .center, - ), - ), - Flexible( - child: IconButton( - 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!, @@ -181,40 +163,28 @@ 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(); - }); - }, + ], ), - ); + ).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 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 7ef0f84..6bc0040 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -1,7 +1,8 @@ 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/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'; import 'package:mohem_flutter_app/classes/utils.dart'; @@ -26,81 +27,80 @@ 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, + ], + ), + ), + ], ), - ); + ).onPress(() { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.favUsersList![index], "isNewChat": false}, + ).then( + (Object? value) { + m.clearSelections(); + }, + ); + }); }, - 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, diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 954c26c..48270d7 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -1,12 +1,15 @@ 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'; 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'; @@ -15,6 +18,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/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'; @@ -26,6 +30,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); @@ -51,13 +58,26 @@ class _DashboardScreenState extends State { scheduleMicrotask(() { data = Provider.of(context, listen: false); marathonProvider = Provider.of(context, listen: false); + _bHubCon(); _onRefresh(); }); } + void buildHubConnection() async { + hubConnection = await data.getHubConnection(); + await hubConnection.start(); + } + @override void dispose() { super.dispose(); + hubConnection.stop(); + } + + void _bHubCon() { + data.getUserAutoLoginToken().whenComplete(() { + buildHubConnection(); + }); } void _onRefresh() async { @@ -87,29 +107,29 @@ class _DashboardScreenState extends State { // 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); + // 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(value.result!.data!.notificationMasterId ?? "").then( + // DashboardApiClient().getAdvertisementDetail(val.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], - // ), - // ), - // ); + // 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!, + // // ), + // // ), + // // ); // } // } // }, 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..a71a71b --- /dev/null +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -0,0 +1,135 @@ +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 { + const ITGAdsScreen({Key? key}) : super(key: key); + + @override + _ITGAdsScreenState createState() => _ITGAdsScreenState(); +} + +class _ITGAdsScreenState extends State { + late Future _futureController; + late VideoPlayerController _controller; + bool skip = false; + bool isVideo = false; + bool isImage = false; + String ext = ''; + late File imageFile; + ads.Advertisement? advertisementData; + dynamic data; + String? masterID; + + void checkFileType() async { + 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!); + isImage = true; + } else { + isVideo = true; + _futureController = createVideoPlayer(rFile!); + } + setState(() {}); + initTimer(); + } + + 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(String encodedBytes) async { + try { + Uint8List decodedBytes = base64Decode(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 initTimer() { + Future.delayed(const Duration(seconds: 5), () { + skip = true; + setState(() {}); + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @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( + children: [ + 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: () async { + // DashboardApiClient().setAdvertisementViewed(widget.addMasterId, widget.advertisement!.advertisementId!).then((value) { + // logger.d(value); + // }); + }, + 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()); - } - }, - ), - ), - ); - } -} diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 803660b..e6b4838 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/ui/marathon/marathon_intro_screen.dart b/lib/ui/marathon/marathon_intro_screen.dart index e9d2cba..d85a82f 100644 --- a/lib/ui/marathon/marathon_intro_screen.dart +++ b/lib/ui/marathon/marathon_intro_screen.dart @@ -26,26 +26,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: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, - ).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: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch,), + ], + ).expanded, + 1.divider, + MarathonFooter(provider: provider), ], ), ); @@ -62,7 +54,7 @@ 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, @@ -136,7 +128,7 @@ 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( @@ -151,15 +143,8 @@ class MarathonTimerCard extends StatelessWidget { DateUtil.formatDateToTimeLang(DateTime.parse(provider.marathonDetailModel.startTime!), AppState().isArabic(context)).toText16(color: MyColors.darkTextColor, isBold: true), ], ), - 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), ], ), ); @@ -180,38 +165,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_screen.dart b/lib/ui/marathon/marathon_screen.dart index 6aa3ee9..79d61fe 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/question_card.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card_builder.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); @@ -103,7 +101,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: [ @@ -111,10 +109,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.marathonDetailModel.totalQuestions.toString()} ${LocaleKeys.question.tr()}" .toText12(color: MyColors.white), @@ -124,38 +119,52 @@ class _MarathonProgressContainerState extends State { .toText18(color: widget.provider.currentQuestionTime < 5 ? MyColors.redColor : MyColors.black), ], ), - 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 / widget.provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}".toText14(isBold: true), + "${((widget.provider.currentQuestionNumber / widget.provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${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), + ); + } } // InkWell( diff --git a/lib/ui/marathon/marathon_winner_selection.dart b/lib/ui/marathon/marathon_winner_selection.dart index 5dcac2b..1f56801 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 0a2936e..e329f92 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/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index fe1f367..af538f8 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -112,7 +112,7 @@ class AnswerContent extends StatelessWidget { Widget build(BuildContext context) { MarathonProvider provider = context.watch(); return Container( - padding: const EdgeInsets.all(13), + padding: const EdgeInsets.symmetric(vertical: 31, horizontal: 13), decoration: const BoxDecoration( color: MyColors.kWhiteColor, borderRadius: BorderRadius.only( 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); } 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}, ); }, - ), ); }, diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index f92f9f4..69bf7e4 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -20,7 +20,7 @@ class ImageOptions { if (Platform.isAndroid) { cameraImageAndroid(image); } else { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); + File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 10))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -33,7 +33,7 @@ class ImageOptions { if (Platform.isAndroid) { galleryImageAndroid(image); } else { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -74,7 +74,7 @@ class ImageOptions { if (Platform.isAndroid) { galleryImageAndroid(image); } else { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -91,7 +91,7 @@ class ImageOptions { if (Platform.isAndroid) { cameraImageAndroid(image); } else { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); + File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 10))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -114,7 +114,7 @@ class ImageOptions { } void galleryImageAndroid(Function(String, File) image) async { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -124,7 +124,7 @@ void galleryImageAndroid(Function(String, File) image) async { } void cameraImageAndroid(Function(String, File) image) async { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); + File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 10))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); 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); diff --git a/pubspec.yaml b/pubspec.yaml index f898345..0f1a7b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,11 +79,6 @@ 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