diff --git a/android/build.gradle b/android/build.gradle index 12dceb5..21e1f2f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -28,6 +28,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 176eb48..2f8758c 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,5 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -#distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip \ No newline at end of file diff --git a/assets/icons/close.svg b/assets/icons/close.svg new file mode 100644 index 0000000..631fcfa --- /dev/null +++ b/assets/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/chat-group.svg b/assets/images/chat-group.svg new file mode 100644 index 0000000..127a793 --- /dev/null +++ b/assets/images/chat-group.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 48f443e..8ff0ea3 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -527,6 +527,8 @@ "noWinner": "حزين! لم يفز أحد اليوم.", "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", + "group" : "مجموعة", + "searchGroup": "مجموعة البحث", "connectHmgWifi": "قم بتوصيل HMG WIFI", "connectedHmgWifi": "اتصال HMG WIFI", "itgForms": "نماذج (ITG)", @@ -537,5 +539,8 @@ "allDocuments": "كافة المستندات", "expiredDocuments": "المستندات منتهية الصلاحية", "missingDocuments": "مستندات مفقودة", - "uploadedDocuments": "المستندات التي تم تحميلها" + "uploadedDocuments": "المستندات التي تم تحميلها", + "addAtLeastOneAttachment": "الرجاء إضافة مرفق واحد على الأقل.", + "pleaseClickButtonToJoinMarathon": "الرجاء الضغط على الزر أدناه للانضمام إلى الماراثون", + "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index b005710..2449802 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -527,6 +527,8 @@ "noWinner": "Sad! No one won today.", "myTeam": "My Team", "youCanPlayDemo": "But you can play demo", + "group": "Groups", + "searchGroup": "Search Group", "connectHmgWifi": "Connect HMG WIFI", "connectedHmgWifi": "Connected HMG WIFI", "itgForms": "ITG Forms", @@ -537,5 +539,27 @@ "allDocuments": "All\nDocuments", "expiredDocuments": "Expired\nDocuments", "missingDocuments": "Missing\nDocuments", - "uploadedDocuments": "Uploaded\nDocuments" + "uploadedDocuments": "Uploaded\nDocuments", + "manage": "Manage", + "members": "Members", + "areYouSureWantTodelete": "Are you sure want to delete?", + "groupMembers": "Group Members", + "manageGroup": "Manage Group", + "admin": "Admin", + "addUsers": "Add users to the group", + "editGroups":"Edit Group", + "groupNameshouldbe": "Group name should be minimum 10 character long", + "enterGroupName": "Please enter valid group Name", + "groupName": "Group Name", + "enterGroupNamePlease": "Please enter group name", + "audioCall": "Audio Call", + "videoCall": "Video Call", + "shareScreen": "Share Screen", + "searchByUserName": "Search By Username", + "userSearch": "User Search", + "userName": "User Name", + "userId": "UserID", + "addAtLeastOneAttachment": "Please add at least one attachment.", + "pleaseClickButtonToJoinMarathon": "Press the button below to join the Marathon.", + "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit." } \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 447afb8..f1f07ca 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -66,7 +66,6 @@ processing fetch remote-notification - voip UILaunchStoryboardName LaunchScreen diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 8518cd7..3fbe57c 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -186,6 +186,13 @@ class ApiClient { } else { headers['Content-Type'] = 'application/json'; } + + if (!kReleaseMode) { + print("Url:$url"); + // var bodyJson = json.encode(jsonObject); + // print("body:$bodyJson"); + } + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); } diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index d127a3a..e9a5afa 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -12,7 +12,11 @@ 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/chat_user_image_model.dart'; +import 'package:mohem_flutter_app/models/chat/create_group_request.dart' as createGroup; +import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart'; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' as groups; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.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; @@ -189,58 +193,121 @@ class ChatApiClient { return imagesData; } - // CallUser Login Token - - Future getUserCallToken({required String userid}) async { - user.UserAutoLoginModel userLoginResponse = user.UserAutoLoginModel(); - Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatLoginTokenUrl}externaluserlogin", - { - "employeeNumber": userid, - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", - }, - ); + //group chat apis start here. + Future getGroupsByUserId() async { + try { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.getGroupByUserId}${AppState().chatDetails!.response!.id}", + token: AppState().chatDetails!.response!.token, + ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + return groups.GetUserGroups.fromRawJson(response.body); + } catch (e) { + //if fail api returning 500 hence just printing here + print(e); + throw e; + } + } - if (!kReleaseMode) { - logger.i("login-res: " + response.body); + Future deleteGroup(int? groupId) async { + try { + Response response = await ApiClient().postJsonForResponse( + ApiConsts.deleteGroup, + {"groupId": groupId}, + token: AppState().chatDetails!.response!.token, + ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + return response; + } catch (e) { + //if fail api returning 500 hence just printing here + print(e); + throw e; } - if (response.statusCode == 200) { - userLoginResponse = user.userAutoLoginModelFromJson(response.body); - } else if (response.statusCode == 501 || response.statusCode == 502 || response.statusCode == 503 || response.statusCode == 504) { - getUserCallToken(userid: userid); - } else { - userLoginResponse = user.userAutoLoginModelFromJson(response.body); - Utils.showToast(userLoginResponse.errorResponses!.first.message!); + } + + Future updateGroupAdmin(int? groupId, List groupList) async { + try { + Response response = await ApiClient().postJsonForResponse( + ApiConsts.updateGroupAdmin, + {"groupId": groupId, "groupUserList": groupList}, + token: AppState().chatDetails!.response!.token, + ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + return response; + } catch (e) { + //if fail api returning 500 hence just printing here + print(e); + throw e; } - return userLoginResponse; } - // Call Decline On App Terminated State - Future callDecline({required int cUserID, required int tUserID, required String targetUsertoken}) async { - Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.chatLoginTokenUrl}calldecline", - {"currentUserId": cUserID, "targetUserId": tUserID, "secretKey": "derichatmobileuser", "targetUserToken": targetUsertoken}, - ); - print("res: " + response.body); - if (!kReleaseMode) { - logger.i({"currentUserId": cUserID, "targetUserId": tUserID, "secretKey": "derichatmobileuser", "targetUserToken": targetUsertoken}); - print("res: " + response.body); + Future> getGroupChatHistory(int? groupId, List groupList) async { + try { + Response response = await ApiClient().postJsonForResponse( + ApiConsts.getGroupChatHistoryAsync, + {"groupId": groupId, "targetUserList": groupList, "CurrentId": AppState().chatDetails!.response!.id}, + token: AppState().chatDetails!.response!.token, + ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + List groupChat = []; + List groupChatData = json.decode(response.body); + for (var i in groupChatData) { + groupChat.add(GetGroupChatHistoryAsync.fromJson(i)); + } + + groupChat.sort((a, b) => b.createdDate!.compareTo(a.createdDate!)); + return groupChat; + // for(GetGroupChatHistoryAsync i in groupChat) { + // return GetGroupChatHistoryAsync.fromJson(jsonEncode(i)); + // } + } catch (e) { + //if fail api returning 500 hence just printing here + print(e); + throw e; } - return response; } - Future oneSignalVoip(String value) async { - String id = ""; - Response response = await ApiClient().postJsonForResponse( - "${ApiConsts.oneSignalCall}players", - {"app_id": ApiConsts.oneSignalAppID, "identifier": value, "device_type": 0, "test_type": !kReleaseMode ? 1 : 0}, - ); + Future addGroupAndUsers(createGroup.CreateGroupRequest request) async { + try { + Response response = await ApiClient().postJsonForResponse( + ApiConsts.addGroupsAndUsers, + request, + token: AppState().chatDetails!.response!.token, + ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + return response.body; + } catch (e) { + //if fail api returning 500 hence just printing here + print(e); + throw e; + } + } - Map values = jsonDecode(response.body) as Map; - id = values["id"]; - if (!kReleaseMode) { - print("res: " + response.body); + Future updateGroupAndUsers(createGroup.CreateGroupRequest request) async { + try { + Response response = await ApiClient().postJsonForResponse( + ApiConsts.updateGroupsAndUsers, + request, + token: AppState().chatDetails!.response!.token, + ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + return response.body; + } catch (e) { + //if fail api returning 500 hence just printing here + print(e); + throw e; } - return id; } } diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 544ba71..77cc37d 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -201,7 +201,7 @@ class DashboardApiClient { }, url, postParams); } - Future setAdvertisementViewed(String masterID, int advertisementId, String ackValue) async { + Future setAdvertisementViewed(String masterID, int advertisementId, String? ackValue) async { String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed"; Map postParams = { diff --git a/lib/api/profile_api_client.dart b/lib/api/profile_api_client.dart index 030a949..342ac31 100644 --- a/lib/api/profile_api_client.dart +++ b/lib/api/profile_api_client.dart @@ -180,7 +180,7 @@ class ProfileApiClient { ], "P_CONTACT_RELATIONSHIP_ID": contactRelationId, "P_ACTION": actionType, - "PayrollCodeStr": "CS", + "PayrollCodeStr": "HMG", "LegislationCodeStr": "SA", }; postParams.addAll(AppState().postParamsJson); diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 628701f..29805ec 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -348,12 +348,12 @@ class WorkListApiClient { }, url, postParams); } - Future getITGFormDetails(String requestType, int taskId, int itemId, String employeeNumber) async { + Future getITGFormDetails(String requestType, taskId, itemId, String employeeNumber) async { String url = "${ApiConsts.cocRest}ITGGetFormDetials"; Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, }; postParams.addAll(AppState().postParamsJson); @@ -363,12 +363,12 @@ class WorkListApiClient { }, url, postParams); } - Future rejectITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { + Future rejectITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async { String url = "${ApiConsts.cocRest}ITGRejectRequest"; Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments, }; @@ -379,12 +379,12 @@ class WorkListApiClient { }, url, postParams); } - Future approveITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { + Future approveITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async { String url = "${ApiConsts.cocRest}ITGApproveRequest"; Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments, }; @@ -395,12 +395,12 @@ class WorkListApiClient { }, url, postParams); } - Future delegateITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { + Future delegateITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGDelegateRequest"; Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "NewUserEMPId": newUserEMPId, "Comments": comments, @@ -414,12 +414,12 @@ class WorkListApiClient { // ANSWER = 'Services/COCWS.svc/REST/ITGAnswer'; - Future answerITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { + Future answerITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGAnswer"; Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments, }; @@ -435,7 +435,7 @@ class WorkListApiClient { Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": "", "AdditionalFields": null, @@ -448,12 +448,12 @@ class WorkListApiClient { }, url, postParams); } - Future informationITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { + Future informationITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGRequestInformation"; Map postParams = { "RequestType": requestType, "TaskID": taskId, - "ItemID": itemId, + "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "NewUserEMPId": newUserEMPId, "Comments": comments, diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index b7dfa34..d4276f4 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.8, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.3, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; @@ -193,8 +193,8 @@ class AppState { } bool cancelRequestTrancsection = true; - - + + String _iosVoipPlayerID = ""; String get iosVoipPlayerID => _iosVoipPlayerID; @@ -202,7 +202,7 @@ class AppState { set setiosVoipPlayerID(String value) { _iosVoipPlayerID = value; } - + bool _isUserOnline = false; bool get getisUserOnline => _isUserOnline; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 318bb81..6c5d40e 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,8 +3,8 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - static String baseUrl = "https://hmgwebservices.com"; // Live server + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; @@ -20,6 +20,14 @@ class ApiConsts { static String chatLoginTokenUrl = chatServerBaseApiUrl + "user/"; static String chatHubConnectionUrl = chatServerBaseUrl + "ConnectionChatHub"; + //Groups + static String getGroupByUserId = chatServerBaseApiUrl + "group/getgroupsbyuserid/"; + static String deleteGroup = chatServerBaseApiUrl + "group/updateGroupIsDeleted/"; + static String updateGroupAdmin = chatServerBaseApiUrl + "group/updateGroupAdmin/"; + static String getGroupChatHistoryAsync = chatServerBaseApiUrl + "GroupChat/GetGroupChatHistoryAsync/"; + static String addGroupsAndUsers = chatServerBaseApiUrl + "group/addgroupandusers/"; + static String updateGroupsAndUsers = chatServerBaseApiUrl + "group/updategroupandusers/"; + // static String chatSearchMember = chatLoginTokenUrl + "user/"; static String chatRecentUrl = chatServerBaseApiUrl + "UserChatHistory/"; //For a Mem static String chatSingleUserHistoryUrl = chatServerBaseApiUrl + "UserChatHistory/"; diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 9c198b3..80f0d79 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -117,7 +117,10 @@ class AppNotifications { debugPrint("HUAWEI PUSH TOKEN: $_huaweiToken"); } - void _onTokenError(Object error) {} + void _onTokenError(Object error) { + debugPrint("HUAWEI PUSH TOKEN ERROR: $error"); + Utils.hideLoading(context); + } Future initTokenStream(Function loginCallback) async { huawei_push.Push.getTokenStream.listen(_onTokenEvent, onError: _onTokenError).onData((data) { diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 7885fad..9c55375 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -349,7 +349,7 @@ class Utils { } static Future selectDate(BuildContext context, DateTime selectedDate) async { - if (Platform.isIOS) { + if (!Platform.isIOS) { await showCupertinoModalPopup( context: context, builder: (BuildContext cxt) => Container( @@ -401,7 +401,6 @@ class Utils { } return false; } - static bool isDate(String input, String format) { try { DateTime d = DateFormat(format).parseStrict(input); diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 2a6ed46..6517deb 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -9,6 +9,9 @@ import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart'; 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/chat/group_chat_detaied_screen.dart'; +import 'package:mohem_flutter_app/ui/chat/group_members.dart'; +import 'package:mohem_flutter_app/ui/chat/manage_group.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; @@ -192,6 +195,10 @@ class AppRoutes { static const String chatFavoriteUsers = "/chatFavoriteUsers"; static const String chatStartCall = "/chatStartCall"; + //Group Chat + static const String manageGroup = "/manageGroup"; + static const String groupMembers = "/groupmembers"; + static const String groupChatDetailed = "/groupChatDetailed"; //Marathon static const String marathonIntroScreen = "/marathonIntroScreen"; static const String marathonScreen = "/marathonScreen"; @@ -306,6 +313,11 @@ class AppRoutes { chatStartCall: (BuildContext context) => StartCallPage(), + //Group Chat + manageGroup: (BuildContext context) => ManageGroupScreen(), + groupMembers: (BuildContext context) => GroupMembersScreen(), + groupChatDetailed: (BuildContext context) => GroupChatDetailScreen(), + // Marathon marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(), marathonScreen: (BuildContext context) => MarathonScreen(), diff --git a/lib/extensions/int_extensions.dart b/lib/extensions/int_extensions.dart index 16bdd29..f46d5bb 100644 --- a/lib/extensions/int_extensions.dart +++ b/lib/extensions/int_extensions.dart @@ -10,6 +10,4 @@ extension IntExtensions on int { Widget get divider => Divider(height: toDouble(), thickness: toDouble(), color: MyColors.lightGreyEFColor); Widget get makeItSquare => SizedBox(width: toDouble(), height: toDouble()); - - } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 45cfc05..3af55f0 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -22,6 +22,32 @@ extension TrimString on String { } } +extension DatePerse on String { + String parseMonth() { + Map monthAbbreviations = { + 'JAN': '01', + 'FEB': '02', + 'MAR': '03', + 'APR': '04', + 'MAY': '05', + 'JUN': '06', + 'JUL': '07', + 'AUG': '08', + 'SEP': '09', + 'OCT': '10', + 'NOV': '11', + 'DEC': '12', + }; + + var split = this.split('-'); + String first = split[0]; + String second = split[1].substring(0, 3); + String third = split[2]; + second = monthAbbreviations[second.toUpperCase()] ?? second; + return DateFormat('yyyy/MM/dd', "en_US").format(DateFormat("dd-MM-yyyy", "en_US").parse("$first-$second-$third")); + } +} + String displayLocalizedContent({required bool isPhoneLangArabic, required int selectedLanguage, required String englishContent, required String arabicContent}) { if (selectedLanguage == 1) { return englishContent; @@ -136,8 +162,9 @@ extension EmailValidator on String { ), ); - Widget toText17({Color? color, bool isBold = false}) => Text( + Widget toText17({Color? color, bool isBold = false, bool isCentered = false}) => Text( this, + textAlign: isCentered ? TextAlign.center : null, style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.68, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); @@ -170,6 +197,12 @@ extension EmailValidator on String { style: TextStyle(height: 1, color: color ?? MyColors.darkTextColor, fontSize: 22, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); + Widget toText23({Color? color, bool isBold = false, bool isCentered = false}) => Text( + this, + textAlign: isCentered ? TextAlign.center : null, + style: TextStyle(height: 23 / 24, color: color ?? MyColors.darkTextColor, fontSize: 23, letterSpacing: -0.92, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + ); + Widget toText24({Color? color, bool isBold = false, bool isCentered = false}) => Text( this, textAlign: isCentered ? TextAlign.center : null, diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index c8bfdfa..a433421 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -6,1095 +6,1108 @@ import 'dart:ui'; import 'package:easy_localization/easy_localization.dart' show AssetLoader; -class CodegenLoader extends AssetLoader{ +class CodegenLoader extends AssetLoader { const CodegenLoader(); @override - Future> load(String fullPath, Locale locale ) { + Future> load(String fullPath, Locale locale) { return Future.value(mapLocales[locale.toString()]); } - static const Map ar_SA = { - "mohemm": "Mohemm", - "english": "English", - "arabic": "عربي", - "login": "تسجيل الدخول", - "pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول", - "username": "اسم المستخدم", - "password": "كلمة المرور", - "welcomeBack": "مرحبا بعودتك", - "wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟", - "lastLoginDetails": "تفاصيل تسجيل الدخول الأخير:", - "verificationType": "نوع التحقق:", - "pleaseVerify": "ارجوك تحقق", - "pleaseVerifyForBio": "الرجاء التحقق من تسجيل الدخول باستخدام أحد هذه الخيارات", - "verifyThroughFace": "تحقق من خلال الوجه", - "verifyThroughFingerprint": "تحقق من خلال بصمة الإصبع", - "verifyThroughSMS": "تحقق من خلال الرسائل القصيرة", - "verifyThroughWhatsapp": "تحقق من خلال Whatsapp", - "useAnotherAccount": "استخدم حسابا آخر", - "pleaseEnterTheVerificationCodeSentTo": "الرجاء إدخال رمز التحقق المرسل إلى ", - "theVerificationCodeWillExpireIn": "ستنتهي صلاحية رمز التحقق في ", - "goodMorning": "صباح الخير", - "markAttendance": "علامة الحضور", - "timeLeftToday": "الوقت المتبقي اليوم", - "checkIn": "تحقق في", - "workList": "قائمة العمل", - "leaveBalance": "رصيد الاجازات", - "missingSwipes": "تسجيل بصمة حضور", - "ticketBalance": "رصيد التذكرة", - "other": "آخر", - "services": "خدمات", - "viewAllServices": "عرض جميع الخدمات", - "monthlyAttendance": "الحضور الشهري", - "vacationRule": "قاعدة الاجازات", - "vacationType": "نوع الاجازة", - "startDateT": "تاريخ البدء", - "endDateT": "تاريخ الانتهاء", - "workFromHome": "العمل من المنزل", - "ticketRequest": "طلب تذكرة", - "viewAllOffers": "مشاهدة جميع العروض", - "offers": "عروض & ", - "discounts": "الخصومات", - "newString": "جديد", - "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", - "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", - "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", - "confirmPassword": "تأكيد كلمة المرور", - "update": "تحديث", - "title": "عنوان", - "home": "الرئيسية", - "mySalary": "راتبي", - "createRequest": "إنشاء طلب", - "forgotPassword": "هل نسيت كلمة السر", - "employeeId": "هوية الموظف", - "loginCodeWillSentToMobileNumber": "الرجاء إدخال معرف الموظف الخاص بك ، وسيتم إرسال رمز تسجيل الدخول إلى رقم هاتفك المحمول", - "changePassword": "تغيير كلمة المرور", - "ok": "موافق", - "confirm": "تؤكد", - "passwordChangedSuccessfully": "تم تغيير الرقم السري بنجاح", - "itemsForSale": "سلع للبيع", - "attendanceDetails": "تفاصيل الحضور", - "order": "الطلبات", - "earlyOut": "الخروج مبكرا", - "shortage": "ساعات التقصير", - "excess": "فائض", - "lateIn": "القدوم المتاخر", - "approvedCheckOut": "اعتماد وقت الخروج", - "approvedCheckIn": "اعتماد وقت الدخول", - "actualCheckOut": "وقت الخروج", - "actualCheckIn": "وقت الدخول", - "present": "حضور", - "pres": "حضور", - "shiftTime": "وقت التناوب", - "absent": "غياب", - "attendance": "الحضور", - "scheduleDays": "ايام العمل", - "offDays": "ايام الراحه", - "nonAnalyzed": "لايوجد تحليل", - "shortageHour": "ساعات التقصير", - "stats": "الحاله", - "completed": "تم اكمال", - "msg": "Hello {} in the {} world ", - "msg_named": "{} are written in the {lang} language", - "clickMe": "Click me", - "doNotUseRecentPassword": "لا تستخدم كلمة مرور حديثة", - "atLeastOneLowercase": "حرف صغير واحد على الأقل", - "atLeastOneUppercase": "حرف كبير واحد على الأقل", - "atLeastOneNumeric": "رقم واحد على الأقل", - "minimum8Characters": "8 أحرف على الأقل", - "doNotAddRepeatingLetters": "لا تقم بإضافة أحرف متكررة", - "itShouldContainSpecialCharacter": "يجب أن يحتوي على طابع خاص", - "confirmPasswordMustMatch": "يجب أن يتطابق تأكيد كلمة المرور", - "sms": "رسالة قصيرة", - "fingerPrint": "بصمة", - "face": "التعرف على الوجه", - "whatsapp": "واتس اب", - "reject": "يرفض", - "approve": "يوافق", - "cancel": "إلغاء", - "requestedItems": "العناصر المطلوبة", - "request": "طلب", - "myRequest": "طلبي", - "actions": "أجراءات", - "delegate": "مندوب", - "request_info": "اطلب معلومات", - "attachments": "المرفقات", - "info": "معلومات", - "employeeNumber": "رقم الموظف", - "assignmentNumber": "رقم الواجب", - "employeeName": "اسم الموظف", - "scheduleDate": "تاريخ الجدول الزمني", - "shiftType": "نوع التحول", - "shift": "يحول", - "breakText": "استراحة", - "actualSwipeStart": "بدء التمرير الفعلي", - "actualSwipeEnd": "التمرير الفعلي للنهاية", - "approvedSwipeStart": "وافق انتقاد البدء", - "approvedSwipeStartReason": "تمت الموافقة على سبب بدء التمرير السريع", - "approvedSwipeEnd": "تمت الموافقة على تمرير النهاية", - "approvedSwipeEndReason": "الموافقة على سبب إنهاء التمرير", - "from": "من", - "to": "ل", - "sent": "أرسلت", - "closed": "مغلق", - "id": "هوية شخصية", - "responder": "المستجيب", - "jobTitle": "عنوان وظيفي", - "grade": "درجة", - "jobCategory": "تصنيف الوظيفة", - "category": "فئة", - "employeeEmailAddress": "عنوان البريد الإلكتروني للموظف", - "payrollBranch": "فرع الرواتب", - "yourChangeHasBeenSavedSuccessfully": "تم حفظ التغيير الخاص بك بنجاح", - "code": "شفرة", - "unit": "وحدة", - "quantity": "كمية", - "dateRequired": "التاريخ مطلوب", - "lineStatus": "حالة الخط", - "statusDate": "تاريخ الحالة", - "transactionType": "نوع المعاملة", - "operatingUnit": "وحدة التشغيل", - "organizationCode": "كود المنظمة", - "organization": "منظمة", - "fromSubInventory": "من الجرد الفرعي", - "fromLocator": "من محدد المواقع", - "toSubInventory": "إلى الجرد الفرعي", - "toLocator": "إلى محدد المواقع", - "shipToLocator": "شحن إلى محدد المواقع", - "itemHistory": "تاريخ العنصر", - "mfg": "مبدع", - "lineType": "نوع الخط", - "price": "السعر", - "lineAmount": "مبلغ الخط", - "lineDiscount": "خصم الخط٪", - "needByDate": "القادمة إلى الأمام", - "promisedDate": "التسجيل وعد", - "deliverToLocation": "تسليم إلى الموقع", - "requisitionNumber": "رقم الطلب", - "requester": "مقدم الطلب", - "quotationAnalysis": "تحليل الاقتباس", - "subject": "موضوعات", - "description": "وصف", - "supplier": "المورد", - "site": "موقع", - "buyer": "مشتر", - "preparer": "معد", - "creationDate": "تاريخ الإنشاء", - "shipToLocation": "الشحن الى الموقع", - "quotationNumber": "رقم الإقتباس", - "quotationDate": "تاريخ الاقتباس", - "paymentTerms": "شروط الدفع", - "currency": "عملة", - "grossAmount": "المبلغ الإجمالي", - "discountAmount": "مقدار الخصم", - "customDuty": "الرسوم الجمركية", - "shipHandle": "مقبض السفينة", - "otherCharges": "رسوم أخرى", - "totalPOAmountWithVAT": "إجمالي مبلغ الشراء مع ضريبة القيمة المضافة", - "totalPOAmountInWords": "إجمالي مبلغ أمر الشراء بالكلمات", - "requestNumber": "رقم الطلب", - "uom": "UOM", - "operatingCode": "كود التشغيل", - "poNumber": "PO عدد", - "revision": "مراجعة", - "quantityOrdered": "الكمية المطلوبة", - "quantityReceived": "الكمية المستلمة", - "bonusQuantity": "كمية المكافأة", - "purchasePrice": "سعر الشراء", - "discountPer": "خصم ٪", - "balanceQuantity": "كمية التوازن", - "netPrice": "السعر الصافي", - "closureStatus": "حالة الإغلاق", - "quotationNetPrice": "صافي سعر الاقتباس", - "quotationUOM": "اقتباس UOM", - "quotationQty": "اقتباس الكمية", - "itemCode": "رمز الصنف", - "vendorName": "اسم البائع", - "quotationMFGPartNumber": "رقم الجزء MFG الاقتباس", - "quotationDeliveryDate": "تاريخ تسليم عرض الأسعار", - "quotationBonusQuantity": "كمية مكافأة الاقتباس", - "quotationLineTotal": "مجموع خط الاقتباس", - "rfqUOM": "RFQ UOM", - "rfqQty": "RFQ الكمية", - "rfqNumber": "رقم RFQ", - "human": "بشري", - "resources": "موارد", - "details": "تفاصيل", - "noDataAvailable": "لا تتوافر بيانات", - "productName": "اسم المنتج", - "productDescription": "وصف المنتج", - "unitPrice": "سعر الوحده", - "manufacturerName": "اسم المصنع", - "manufacturerPartName": "اسم جزء الشركة المصنعة", - "supplierName": "اسم المورد", - "supplierContact": "الاتصال بالمورد", - "chargeToPatient": "المسؤول عن المريض", - "justification": "التبرير", - "itemDescription": "وصف السلعة", - "groupCode": "كود المجموعة", - "primaryUOM": "UOM الابتدائية", - "subgroupDescription": "وصف المجموعة الفرعية", - "subgroupCode": "رمز المجموعة الفرعية", - "groupDescription": "وصف المجموعة", - "templateName": "اسم القالب", - "itemCreationStatus": "حالة إنشاء العنصر", - "standardizationApprovalStatus": "حالة الموافقة على التقييس", - "standardizationApprovalRejectionReason": "سبب رفض الموافقة على التقييس", - "analyzedBy": "تحليل بواسطة", - "approvedDate": "تاريخ الموافقة", - "itemType": "نوع العنصر", - "relatedTo": "متعلق ب", - "requestDate": "تاريخ الطلب", - "analyzedDate": "تاريخ التحليل", - "urgent": "العاجلة", - "requestDetails": "طلب تفاصيل", - "approvalLevel": "مستوى الموافقة", - "requesterDetails": "تفاصيل مقدم الطلب", - "myAttendance": "حضوري", - "workOnBreak": "التعويض عن العمل اثناءالاستراحه", - "next": "التالي", - "apply": "يتقدم", - "mobile": "التليفون المحمول", - "completingYear": "نحن نقدر لك لاستكمال خدمة", - "year": "سنة", - "month": "شهر", - "day": "يوم", - "address": "العنوان", - "phoneNumber": "رقم الجوال", - "businessGroup": "مجموعة العمل", - "Payroll": "الراتب", - "civilIdentityNumber": "رقم الهويه", - "dateOfBirth": "تاريخ الميلاد", - "maritalStatus ": "الحالة الاجتماعية", - "fullName": "الأسم الكامل", - "remove": "حذف", - "submit": "ارسال", - "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", - "comments": "تعليقات", - "writeComment": "أكتب تعليقا", - "approversList": "قائمة الموافقين", - "yourRequestHasBeenSubmittedForApprovals": "تم تقديم طلبك للموافقات", - "monthlyPaySlip": "قسيمة الراتب الشهرية", - "particular": "خاص", - "earnings": "أرباح", - "deductions": "الخصومات", - "paymentMethodName": "اسم طريقة الدفع", - "bankName": "اسم البنك", - "branchCode": "رمز الفرع", - "accountNo": "رقم الحساب", - "summaryOfInformation": "ملخص المعلومات", - "totalPayAmount": "المبلغ الإجمالي للدفع", - "paymentInformation": "معلومات الدفع", - "performance": "تقييم الاداء", - "performanceEvaluation": "تقييم الأداء في", - "performanceEvaluationIn": "تقييم أدائك في", - "valuationIn": "تقييم الأداء في", - "amount": "مقدار", - "correctCurrentDatails": "تعديل او اكمال التفاصيل الحالية", - "selectType": " حدد نوع التغيير الذي تريد القيام به", - "enterNewInfo": " أدخل معلومات جديدة بسبب تغيير حقيقي في التفاصيل الحالية (على سبيل المثال بسبب تغيير في الحالة الاجتماعية", - "endDate": "تاريخ الانتهاء", - "removeThisMember": "هل انت متأكد تريد ازالة هذا العضو؟", - "wantUpdateThisMember ": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", - "addNewFamilyMember": "اضافة عضو جديد", - "addRow": "اضافة صف جديد", - "pleaseSelect": "الرجاء اختيار", - "delete": "حذف", - "edit": "تعديل", - "add": "اضافه", - "myProfile": "معلوماتي", - "mowadhafhi": "موظفي", - "searchAnnouncements": "بحث الاعلانات", - "announcements": "اعلانات", - "swipeRequest": "طلب تسجيل حضور", - "serviceType": "نوع الخدمه", - "departmentName": "اسم القسم", - "selectDepartment": "اختر القسم", - "relatedSection": "قسم ذو صله", - "selectSection": "اختيار القسم", - "relatedTopic": "عنوان ذو صله", - "selectTopic": "اختر العنوان", - "supportingDocument": "ارفاق مستند", - "mowadhafhiRequest": "طلب موظفي", - "ticketReference": "مرجع التذكره", - "section": "القسم", - "topic": "العنوان", - "actionBy": "الرد بواسطة", - "pending": "معلق", - "pendingTransactions": "المعاملات المعلقه", - "selectRequestType": "الرجاء اختيار نوع الطلب", - "dateFrom": "من تاريخ", - "dateTo": "الى تاريخ", - "requestName": "اسم الطلب", - "createdFor": "انشاء لأجل", - "requestCreatedSuccessfully": "تم انشاء الطلب بنجاح", - "search": "بحث", - "wantToReject": "هل انت متأكد تريد الرفض", - "requestType": "نوع الطلب", - "employeeDigitalID": "هويةالموظف الرقمية", - "businessCard": "بطاقة العمل", - "viewBusinessCard": "عرض بطاقة العمل", - "logout": "تسجيل خروج", - "checkOut": "وقت الخروج", - "regular": "منتظم", - "mark": "علامة", - "selectMethodOfAttendance": "اختر طريقة تسجيل الحضور", - "comeNearHMGWifi": "HMG wifi من فضلك اقترب من", - "deliverNotificationToMeRegardless": "تسليم الإخطارات إلي بغض النظر عن أي قواعد عامة", - "close": "أغلق", - "respond": "يرد", - "vacationRuleAdded": "تمت إضافة قاعدة الإجازة", - "selectTypeT": "اختر صنف", - "notification": "تنبيه", - "selectNotification": "حدد إعلام", - "ifAllSelectedYouWillSkip": "* إذا تم تحديد الكل ، فستنتقل إلى الخطوة 3", - "applyForVacationRule": "التقدم بطلب للحصول على قانون الإجازة", - "step1": "الخطوة 1", - "step2": "الخطوة 2", - "step3": "الخطوه 3", - "message": "رسالة", - "writeAMessage": "اكتب رسالة", - "notificationReassign": "إعادة تعيين الإخطار", - "selectEmployee": "حدد الموظف", - "searchEmployeeForReplacement": "ابحث عن موظف بديل", - "searchForEmployee": "ابحث عن موظف", - "pleaseSpecifyEndTime": "الرجاء تحديد وقت الانتهاء", - "pleaseSelectNotificationReassign": "يرجى تحديد إعادة تعيين الإخطار", - "pleaseSelectEmployeeForReplacement": "الرجاء تحديد موظف للاستبدال", - "pleaseSelectAction": "الرجاء تحديد الإجراء", - "pleaseSelectDate": "الرجاء تحديد التاريخ", - "todayAttendance": "حضور اليوم", - "viewAttendance": "عرض الحضور", - "teamMembers": "اعضاءالفريق", - "profileDetails": "الملف الشخصي", - "noResultsFound": "لايوجد نتائج", - "searchBy": "بحث بواسطة", - "myTeamMembers": "اعضاء فريقي", - "save": "حفظ", - "TurnNotificationsFor": "تفعيل الاشعارات", - "worklistSettings": "اعدادات الاشعارات", - "absenceType": "نوع الغياب", - "absenceCategory": "فئة الغياب", - "days": "أيام", - "hours": "ساعات", - "approvalStatus": "حالة القبول", - "absenceStatus": "حالة الغياب", - "subordinateLeave": "إجازة التابعيين", - "numberDays": "عدد الأيام", - "poweredBy": "مشغل بواسطة", - "cloudSolutions": "حلول السحابة", - "selectTemplate": "حدد قالب", - "myPostedAds": "إعلاناتي المنشورة", - "browseCategories": "تصفح الفئات", - "searchItems": "عناصر البحث", - "offerAndDiscounts": "العروض والخصومات", - "offerValid": "العرض صالح", - "offerExpired": "انتهى العرض", - "whatAreYouOffering": "ما الذي تعرضه؟", - "selectCategory": "اختر الفئة", - "inProgress": "في تَقَدم", - "locked": "مقفل", - "addDetails": "أضف التفاصيل", - "reviewAndSell": "مراجعة وبيع", - "itemTitle": "عنوان البند", - "itemCondition": "حالة السلعة", - "used": "تستخدم", - "region": "منطقة", - "selectRegion": "اختر المنطقة", - "itemPrice": "سعر السلعة", - "itemPhotos": "صور البند", - "itemInfo": "معلومات العنصر", - "uploadAttachment": "تحميل المرفق", - "selectFromGalleryOrOpenCamera": "اختر من المعرض أو فتح الكاميرا", - "openCamera": "فتح\nالكاميرا", - "uploadFromGallery": "تحميل من\nملفات الجهاز", - "name": "الأسم", - "email": "ايميل", - "noHistoryAvailable": "لايوجد سجل بيانات سابقة ", - "purchaseRequisition": "طلب شراء", - "moveOrder": "طلب تغيير", - "humanResource": "الموارد البشريه", - "purchaseOrder": "امر شراء", - "ITGForms": "ITG نماذج", - "itemCreation": "أنشاء عنصر", - "stamp": "ختم", - "addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله", - "feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم", - "rateUI": "كيف تريد أن تقيم", - "rateUI2": "ما مدى رضائك عن هذا التطبيق", - "submitSurvey": "ارسال الاستبيان", - "typeHere": "اكتب هنا", - "infoDetail": "تفاصيل المعلومات", - "amount_detail": "تفاصيل المبلغ", - "currentBalance": "الرصيد الحالي", - "currentLeaveBalance": "رصيد الاجازات الحالي", - "calculatedDays": "الايام المحسوبه", - "totalDays": "مجموع الأيام", - "usedBalance": "المستخدم", - "infants": "رضيع", - "child": "طفل", - "adult": "بالغ", - "updateMember": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", - "fieldIsEmpty": "'{data}' الحقل فارغ. الرجاء التحديد", - "pleaseEnterComments": "الرجاء إدخال التعليقات", - "skip": "يتخطى", - "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", - "currentPassword": "كلمة المرور الحاليه", - "concurrentReports": "التقارير المتزامنه", - "EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت", - "CorrectAddress": "تصحيح أو تعديل هذا العنوان", - "SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.", - "profile": { - "reset_password": { - "label": "Reset Password", - "username": "Username", - "password": "password" - }, - "profileCompletionPer": "استكمال الملف الشخصي", - "completeProfile": "الملف الشخصي الكامل", - "personalInformation": "معلومات شخصية", - "basicDetails": "تفاصيل أساسية", + static const Map ar_SA = { + "mohemm": "Mohemm", + "english": "English", + "arabic": "عربي", + "login": "تسجيل الدخول", + "pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول", + "username": "اسم المستخدم", + "password": "كلمة المرور", + "welcomeBack": "مرحبا بعودتك", + "wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟", + "lastLoginDetails": "تفاصيل تسجيل الدخول الأخير:", + "verificationType": "نوع التحقق:", + "pleaseVerify": "ارجوك تحقق", + "pleaseVerifyForBio": "الرجاء التحقق من تسجيل الدخول باستخدام أحد هذه الخيارات", + "verifyThroughFace": "تحقق من خلال الوجه", + "verifyThroughFingerprint": "تحقق من خلال بصمة الإصبع", + "verifyThroughSMS": "تحقق من خلال الرسائل القصيرة", + "verifyThroughWhatsapp": "تحقق من خلال Whatsapp", + "useAnotherAccount": "استخدم حسابا آخر", + "pleaseEnterTheVerificationCodeSentTo": "الرجاء إدخال رمز التحقق المرسل إلى ", + "theVerificationCodeWillExpireIn": "ستنتهي صلاحية رمز التحقق في ", + "goodMorning": "صباح الخير", + "markAttendance": "علامة الحضور", + "timeLeftToday": "الوقت المتبقي اليوم", + "checkIn": "تحقق في", + "workList": "قائمة العمل", + "leaveBalance": "رصيد الاجازات", + "missingSwipes": "تسجيل بصمة حضور", + "ticketBalance": "رصيد التذكرة", + "other": "آخر", + "services": "خدمات", + "viewAllServices": "عرض جميع الخدمات", + "monthlyAttendance": "الحضور الشهري", + "vacationRule": "قاعدة الاجازات", + "vacationType": "نوع الاجازة", + "startDateT": "تاريخ البدء", + "endDateT": "تاريخ الانتهاء", + "workFromHome": "العمل من المنزل", + "ticketRequest": "طلب تذكرة", + "viewAllOffers": "مشاهدة جميع العروض", + "offers": "عروض & ", + "discounts": "الخصومات", + "newString": "جديد", + "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", + "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", + "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", + "confirmPassword": "تأكيد كلمة المرور", + "update": "تحديث", + "title": "عنوان", + "home": "الرئيسية", + "mySalary": "راتبي", + "createRequest": "إنشاء طلب", + "forgotPassword": "هل نسيت كلمة السر", + "employeeId": "هوية الموظف", + "loginCodeWillSentToMobileNumber": "الرجاء إدخال معرف الموظف الخاص بك ، وسيتم إرسال رمز تسجيل الدخول إلى رقم هاتفك المحمول", + "changePassword": "تغيير كلمة المرور", + "ok": "موافق", + "confirm": "تؤكد", + "passwordChangedSuccessfully": "تم تغيير الرقم السري بنجاح", + "itemsForSale": "سلع للبيع", + "attendanceDetails": "تفاصيل الحضور", + "order": "الطلبات", + "earlyOut": "الخروج مبكرا", + "shortage": "ساعات التقصير", + "excess": "فائض", + "lateIn": "القدوم المتاخر", + "approvedCheckOut": "اعتماد وقت الخروج", + "approvedCheckIn": "اعتماد وقت الدخول", + "actualCheckOut": "وقت الخروج", + "actualCheckIn": "وقت الدخول", + "present": "حضور", + "pres": "حضور", + "shiftTime": "وقت التناوب", + "absent": "غياب", + "attendance": "الحضور", + "scheduleDays": "ايام العمل", + "offDays": "ايام الراحه", + "nonAnalyzed": "لايوجد تحليل", + "shortageHour": "ساعات التقصير", + "stats": "الحاله", + "completed": "تم اكمال", + "msg": "Hello {} in the {} world ", + "msg_named": "{} are written in the {lang} language", + "clickMe": "Click me", + "doNotUseRecentPassword": "لا تستخدم كلمة مرور حديثة", + "atLeastOneLowercase": "حرف صغير واحد على الأقل", + "atLeastOneUppercase": "حرف كبير واحد على الأقل", + "atLeastOneNumeric": "رقم واحد على الأقل", + "minimum8Characters": "8 أحرف على الأقل", + "doNotAddRepeatingLetters": "لا تقم بإضافة أحرف متكررة", + "itShouldContainSpecialCharacter": "يجب أن يحتوي على طابع خاص", + "confirmPasswordMustMatch": "يجب أن يتطابق تأكيد كلمة المرور", + "sms": "رسالة قصيرة", + "fingerPrint": "بصمة", + "face": "التعرف على الوجه", + "whatsapp": "واتس اب", + "reject": "يرفض", + "approve": "يوافق", + "cancel": "إلغاء", + "requestedItems": "العناصر المطلوبة", + "request": "طلب", + "myRequest": "طلبي", + "actions": "أجراءات", + "delegate": "مندوب", + "request_info": "اطلب معلومات", + "attachments": "المرفقات", + "info": "معلومات", + "employeeNumber": "رقم الموظف", + "assignmentNumber": "رقم الواجب", + "employeeName": "اسم الموظف", + "scheduleDate": "تاريخ الجدول الزمني", + "shiftType": "نوع التحول", + "shift": "يحول", + "breakText": "استراحة", + "actualSwipeStart": "بدء التمرير الفعلي", + "actualSwipeEnd": "التمرير الفعلي للنهاية", + "approvedSwipeStart": "وافق انتقاد البدء", + "approvedSwipeStartReason": "تمت الموافقة على سبب بدء التمرير السريع", + "approvedSwipeEnd": "تمت الموافقة على تمرير النهاية", + "approvedSwipeEndReason": "الموافقة على سبب إنهاء التمرير", + "from": "من", + "to": "ل", + "sent": "أرسلت", + "closed": "مغلق", + "id": "هوية شخصية", + "responder": "المستجيب", + "jobTitle": "عنوان وظيفي", + "grade": "درجة", + "jobCategory": "تصنيف الوظيفة", + "category": "فئة", + "employeeEmailAddress": "عنوان البريد الإلكتروني للموظف", + "payrollBranch": "فرع الرواتب", + "yourChangeHasBeenSavedSuccessfully": "تم حفظ التغيير الخاص بك بنجاح", + "code": "شفرة", + "unit": "وحدة", + "quantity": "كمية", + "dateRequired": "التاريخ مطلوب", + "lineStatus": "حالة الخط", + "statusDate": "تاريخ الحالة", + "transactionType": "نوع المعاملة", + "operatingUnit": "وحدة التشغيل", + "organizationCode": "كود المنظمة", + "organization": "منظمة", + "fromSubInventory": "من الجرد الفرعي", + "fromLocator": "من محدد المواقع", + "toSubInventory": "إلى الجرد الفرعي", + "toLocator": "إلى محدد المواقع", + "shipToLocator": "شحن إلى محدد المواقع", + "itemHistory": "تاريخ العنصر", + "mfg": "مبدع", + "lineType": "نوع الخط", + "price": "السعر", + "lineAmount": "مبلغ الخط", + "lineDiscount": "خصم الخط٪", + "needByDate": "القادمة إلى الأمام", + "promisedDate": "التسجيل وعد", + "deliverToLocation": "تسليم إلى الموقع", + "requisitionNumber": "رقم الطلب", + "requester": "مقدم الطلب", + "quotationAnalysis": "تحليل الاقتباس", + "subject": "موضوعات", + "description": "وصف", + "supplier": "المورد", + "site": "موقع", + "buyer": "مشتر", + "preparer": "معد", + "creationDate": "تاريخ الإنشاء", + "shipToLocation": "الشحن الى الموقع", + "quotationNumber": "رقم الإقتباس", + "quotationDate": "تاريخ الاقتباس", + "paymentTerms": "شروط الدفع", + "currency": "عملة", + "grossAmount": "المبلغ الإجمالي", + "discountAmount": "مقدار الخصم", + "customDuty": "الرسوم الجمركية", + "shipHandle": "مقبض السفينة", + "otherCharges": "رسوم أخرى", + "totalPOAmountWithVAT": "إجمالي مبلغ الشراء مع ضريبة القيمة المضافة", + "totalPOAmountInWords": "إجمالي مبلغ أمر الشراء بالكلمات", + "requestNumber": "رقم الطلب", + "uom": "UOM", + "operatingCode": "كود التشغيل", + "poNumber": "PO عدد", + "revision": "مراجعة", + "quantityOrdered": "الكمية المطلوبة", + "quantityReceived": "الكمية المستلمة", + "bonusQuantity": "كمية المكافأة", + "purchasePrice": "سعر الشراء", + "discountPer": "خصم ٪", + "balanceQuantity": "كمية التوازن", + "netPrice": "السعر الصافي", + "closureStatus": "حالة الإغلاق", + "quotationNetPrice": "صافي سعر الاقتباس", + "quotationUOM": "اقتباس UOM", + "quotationQty": "اقتباس الكمية", + "itemCode": "رمز الصنف", + "vendorName": "اسم البائع", + "quotationMFGPartNumber": "رقم الجزء MFG الاقتباس", + "quotationDeliveryDate": "تاريخ تسليم عرض الأسعار", + "quotationBonusQuantity": "كمية مكافأة الاقتباس", + "quotationLineTotal": "مجموع خط الاقتباس", + "rfqUOM": "RFQ UOM", + "rfqQty": "RFQ الكمية", + "rfqNumber": "رقم RFQ", + "human": "بشري", + "resources": "موارد", + "details": "تفاصيل", + "noDataAvailable": "لا تتوافر بيانات", + "productName": "اسم المنتج", + "productDescription": "وصف المنتج", + "unitPrice": "سعر الوحده", + "manufacturerName": "اسم المصنع", + "manufacturerPartName": "اسم جزء الشركة المصنعة", + "supplierName": "اسم المورد", + "supplierContact": "الاتصال بالمورد", + "chargeToPatient": "المسؤول عن المريض", + "justification": "التبرير", + "itemDescription": "وصف السلعة", + "groupCode": "كود المجموعة", + "primaryUOM": "UOM الابتدائية", + "subgroupDescription": "وصف المجموعة الفرعية", + "subgroupCode": "رمز المجموعة الفرعية", + "groupDescription": "وصف المجموعة", + "templateName": "اسم القالب", + "itemCreationStatus": "حالة إنشاء العنصر", + "standardizationApprovalStatus": "حالة الموافقة على التقييس", + "standardizationApprovalRejectionReason": "سبب رفض الموافقة على التقييس", + "analyzedBy": "تحليل بواسطة", + "approvedDate": "تاريخ الموافقة", + "itemType": "نوع العنصر", + "relatedTo": "متعلق ب", + "requestDate": "تاريخ الطلب", + "analyzedDate": "تاريخ التحليل", + "urgent": "العاجلة", + "requestDetails": "طلب تفاصيل", + "approvalLevel": "مستوى الموافقة", + "requesterDetails": "تفاصيل مقدم الطلب", + "myAttendance": "حضوري", + "workOnBreak": "التعويض عن العمل اثناءالاستراحه", + "next": "التالي", + "apply": "يتقدم", + "mobile": "التليفون المحمول", + "completingYear": "نحن نقدر لك لاستكمال خدمة", + "year": "سنة", + "month": "شهر", + "day": "يوم", "address": "العنوان", - "contactDetails": "بيانات التواصل", - "familyDetails": "تفاصيل عائلية", - "effectiveDate": "تاريخ النفاذ", - "country": "دولة" - }, - "clicked": { - "zero": "You clicked {} times!", - "one": "You clicked {} time!", - "two": "You clicked {} times!", - "few": "You clicked {} times!", - "many": "You clicked {} times!", - "other": "You clicked {} times!" - }, - "gender": { - "male": "Hi man ;) ", - "female": "Hello girl :)", - "with_arg": { - "male": "Hi man ;) {}", - "female": "Hello girl :) {}" - } - }, - "reset_locale": "إعادة ضبط اللغة", - "chat": "دردشة", - "mychats": "دردشاتي", - "advancedSearch": "بحث متقدم", - "openNot": "التبليغات المفتوحة", - "fyi": "تبليغات للعلم", - "toDo": "تبليغات الأعمال", - "all": "كل التبليغات", - "meNot": "تبليغات صادرة مني", - "view": "عرض", - "fromUserName": "من", - "sentDate": "تاريخ الإرسال", - "itemTypeDisplayName": "اسم العرض", - "none": "بدون", - "createNewChat": "إنشاء محادثة جديدة", - "brainMarathon": "ماراثون الدماغ", - "contestTopicAbout": "سيكون موضوع المسابقة حول:", - "gameDate": "تاريخ اللعبة:", - "gameTime": "وقت اللعب:", - "joinMarathon": "انضم إلى ماراثون", - "joinDemoMarathon": "انضم إلى الماراثون التجريبي", - "demo": "تجريبي", - "minutes": "الدقائق", - "seconds": "ثواني", - "note": "ملحوظة:", - "demoMarathonNoteP1": "يمكنك لعب ماراثون العرض لتتعلم كيف يعمل. يمكنك الانضمام إلى ماراثون", - "demoMarathonNoteP2": "خمس دقائق", - "demoMarathonNoteP3": "قبل الوقت الفعلي.", - "sponsoredBy": "برعاية:", - "question": "سؤال", - "marathoners": "الماراثون", - "marathoner": "ماراثونر", - "prize": "جائزة:", - "winnerSelection": "اختيار الفائز", - "qualifiers": "تصفيات", - "qualifier": "المؤهل", - "getReadyForContest": "استعد للمسابقة القادمة:", - "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", - "fingersCrossed": "تشابك الاصابع!!!", - "congrats": "مبروك !!!", - "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", - "otp": "OTP", - "verification": "تَحَقّق", - "resend": "إعادة إرسال", - "codeExpire": "انتهت صلاحية رمز التحقق", - "typeheretoreply": "اكتب هنا للرد", - "favorite": "مفضلتي", - "searchfromchat": "البحث من الدردشة", - "yourAnswerCorrect": "إجابتك صحيحة", - "youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", - "wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", - "oops": "أوه!!!", - "winner": "الفائز", - "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", - "ourSponsor": "راعينا:", - "startingIn": "يبدأ في", - "youAreOutOfContest": "أنت خارج المسابقة.", - "winners": "الفائزين!!!", - "expireAfter": "تنتهي بعد", - "oneWeek": "أسبوع 1", - "twoWeek": "2 أسبوع", - "noUpcoming": "لا يوجد قادم", - "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", - "noWinner": "حزين! لم يفز أحد اليوم.", - "myTeam": "فريقي", - "youCanPlayDemo": "لكن يمكنك لعب العرض", - "connectHmgWifi": "قم بتوصيل HMG WIFI", - "connectedHmgWifi": "اتصال HMG WIFI", - "itgForms": "نماذج (ITG)", - "resetAdPassword": "إعادة تعيين كلمة مرور AD", - "myDocuments": "مستنداتي", - "requiredDocuments": "المستندات المطلوبة", - "optionalDocuments": "المستندات الاختيارية", - "allDocuments": "كافة المستندات", - "expiredDocuments": "المستندات منتهية الصلاحية", - "missingDocuments": "مستندات مفقودة", - "uploadedDocuments": "المستندات التي تم تحميلها" -}; -static const Map en_US = { - "mohemm": "Mohemm", - "english": "English", - "arabic": "عربي", - "login": "Login", - "pleaseEnterLoginDetails": "Please enter the detail below to login", - "username": "Username", - "password": "Password", - "welcomeBack": "Welcome back", - "wouldYouLikeToLoginWithCurrentUsername": "Would you like to login with current Username?", - "lastLoginDetails": "Last Login Details:", - "verificationType": "Verification Type:", - "pleaseVerify": "Please Verify", - "pleaseVerifyForBio": "Please verify login with one of the following options", - "verifyThroughFace": "Verify Through Face", - "verifyThroughFingerprint": "Verify Through Fingerprint", - "verifyThroughSMS": "Verify Through SMS", - "verifyThroughWhatsapp": "Verify Through Whatsapp", - "useAnotherAccount": "Use Another Account", - "pleaseEnterTheVerificationCodeSentTo": "Please enter the verification code sent to ", - "theVerificationCodeWillExpireIn": "The verification code will expire in ", - "goodMorning": "Good Morning", - "markAttendance": "Mark Attendance", - "timeLeftToday": "Time Left Today", - "checkIn": "Check In", - "workList": "Work List", - "leaveBalance": "Leave Balance", - "missingSwipes": "Missing Swipes", - "ticketBalance": "Ticket Balance", - "other": "Other", - "services": "Services", - "viewAllServices": "View All Services", - "monthlyAttendance": "Monthly Attendance", - "vacationRule": "Vacation Rule", - "vacationType": "Vacation Type", - "startDateT": "Start Date", - "endDateT": "End Date", - "workFromHome": "Work From Home", - "ticketRequest": "Ticket Request", - "viewAllOffers": "View All Offers", - "offers": "Offers & ", - "discounts": "Discounts", - "newString": "New", - "setTheNewPassword": "Set the new password", - "typeYourNewPasswordBelow": "Type your new password below", - "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", - "confirmPassword": "Confirm Password", - "update": "Update", - "title": "Title", - "home": "Home", - "mySalary": "My Salary", - "createRequest": "Create Request", - "forgotPassword": "Forgot Password", - "employeeId": "Employee ID", - "loginCodeWillSentToMobileNumber": "Please Enter your Employee ID, A login code will be sent to your mobile number", - "changePassword": "Change Password", - "ok": "OK", - "confirm": "Confirm", - "passwordChangedSuccessfully": "Password changed successfully", - "itemsForSale": "Items for Sale", - "attendanceDetails": "Attendance Details", - "order": "order", - "earlyOut": "Early Out", - "shortage": "Shortage", - "excess": "Excess", - "lateIn": "Late In", - "approvedCheckOut": "Approved Check Out", - "approvedCheckIn": "Approved Check In", - "actualCheckOut": "Actual Check Out", - "actualCheckIn": "Actual Check In", - "present": "PRESENT", - "pres": "present", - "shiftTime": "Shift Time", - "absent": "ABSENT", - "attendance": "Attendance", - "scheduleDays": "Schedule\nDays", - "offDays": "Off\nDays", - "nonAnalyzed": "Non\nAnalyzed", - "shortageHour": "Shortage\nHour", - "stats": "Stats", - "completed": "Completed", - "doNotUseRecentPassword": "Do not use recent password", - "atLeastOneLowercase": "At least one lowercase", - "atLeastOneUppercase": "At least one uppercase", - "atLeastOneNumeric": "At least one numeric", - "minimum8Characters": "Minimum 8 characters", - "doNotAddRepeatingLetters": "Do not add repeating letters", - "itShouldContainSpecialCharacter": "It should contain special character", - "confirmPasswordMustMatch": "Confirm password must match", - "sms": "SMS", - "fingerPrint": "Fingerprint", - "face": "Face", - "whatsapp": "Whatsapp", - "reject": "Reject", - "approve": "Approve", - "cancel": "Cancel", - "requestedItems": "Requested Items", - "request": "Request", - "myRequest": "My Request", - "actions": "Actions", - "delegate": "Delegate", - "request_info": "Request Info", - "attachments": "Attachments", - "info": "Info.", - "employeeNumber": "Employee Number", - "assignmentNumber": "Assignment Number", - "employeeName": "Employee Name", - "scheduleDate": "Schedule Date", - "shiftType": "Shift Type", - "shift": "Shift", - "breakText": "Break", - "actualSwipeStart": "Actual Swipe Start", - "actualSwipeEnd": "Actual Swipe End", - "approvedSwipeStart": "Approved Swipe Start", - "approvedSwipeStartReason": "Approved Swipe Start Reason", - "approvedSwipeEnd": "Approved Swipe End", - "approvedSwipeEndReason": "Approved Swipe End Reason", - "from": "From", - "to": "To", - "sent": "Sent", - "closed": "Closed", - "id": "ID", - "responder": "Responder", - "jobTitle": "Job Title", - "grade": "Grade", - "jobCategory": "Job Category", - "category": "Category", - "employeeEmailAddress": "Employee Email Address", - "payrollBranch": "Payroll Branch", - "yourChangeHasBeenSavedSuccessfully": "Your change has been saved successfully", - "code": "Code", - "unit": "Unit", - "quantity": "Quantity", - "dateRequired": "Date Required", - "lineStatus": "Line Status", - "statusDate": "Status Date", - "transactionType": "Transaction Type", - "operatingUnit": "Operating Unit", - "organizationCode": "Organization Code", - "organization": "Organization", - "fromSubInventory": "From Sub Inventory", - "fromLocator": "From Locator", - "toSubInventory": "To Sub Inventory", - "toLocator": "To Locator", - "shipToLocator": "Ship To Locator", - "itemHistory": "Item History", - "mfg": "MFG", - "lineType": "Line Type", - "price": "Price", - "lineAmount": "Line Amount", - "lineDiscount": "Line Discount %", - "needByDate": "Need By Date", - "promisedDate": "Promised Date", - "deliverToLocation": "Deliver To Location", - "requisitionNumber": "Requisition Number", - "requester": "Requester", - "subject": "Subject", - "quotationAnalysis": "Quotation Analysis", - "description": "Description", - "supplier": "Supplier", - "site": "Site", - "buyer": "Buyer", - "preparer": "Preparer", - "creationDate": "Creation Date", - "shipToLocation": "Ship To Location", - "quotationNumber": "Quotation Number", - "quotationDate": "Quotation Date", - "paymentTerms": "Payment Terms", - "currency": "Currency", - "grossAmount": "Gross Amount", - "discountAmount": "Discount Amount", - "customDuty": "Custom Duty", - "shipHandle": "Ship Handle", - "otherCharges": "Other Charges", - "totalPOAmountWithVAT": "Total PO Amount With VAT", - "totalPOAmountInWords": "Total PO Amount In Words", - "requestNumber": "Request Number", - "uom": "UOM", - "operatingCode": "Operating Code", - "poNumber": "PO Number", - "revision": "Revision", - "quantityOrdered": "Quantity Ordered", - "quantityReceived": "Quantity Received", - "bonusQuantity": "Bonus Quantity", - "purchasePrice": "Purchase Price", - "discountPer": "Discount %", - "balanceQuantity": "Balance Quantity", - "netPrice": "Net Price", - "closureStatus": "Closure Status", - "quotationNetPrice": "Quotation Net Price", - "quotationUOM": "Quotation UOM", - "quotationQty": "Quotation Qty", - "itemCode": "item Code", - "vendorName": "Vendor Name", - "quotationMFGPartNumber": "Quotation MFG Part Number", - "quotationDeliveryDate": "Quotation Delivery Date", - "quotationBonusQuantity": "Quotation Bonus Quantity", - "quotationLineTotal": "Quotation Line Total", - "rfqUOM": "RFQ UOM", - "rfqQty": "RFQ Qty", - "rfqNumber": "RFQ Number", - "msg": "Hello {} in the {} world ", - "msg_named": "{} are written in the {lang} language", - "clickMe": "Click me", - "human": "Human", - "resources": "Resources", - "details": "Details", - "noDataAvailable": "No Data Available", - "productName": "Product Name", - "productDescription": "Product Description", - "unitPrice": "Unit Price", - "manufacturerName": "Manufacturer Name", - "manufacturerPartName": "Manufacturer Part Name", - "supplierName": "Supplier Name", - "supplierContact": "Supplier Contact", - "chargeToPatient": "Charge To Patient", - "justification": "Justification", - "itemDescription": "Item Description", - "groupCode": "Group Code", - "primaryUOM": "Primary UOM", - "subgroupDescription": "Subgroup Description", - "subgroupCode": "Subgroup Code", - "groupDescription": "Group Description", - "templateName": "Template Name", - "itemCreationStatus": "Item Creation Status", - "standardizationApprovalStatus": "Standardization Approval Status", - "standardizationApprovalRejectionReason": "Standardization Approval Rejection Reason", - "analyzedBy": "Analyzed By", - "approvedDate": "Approved Date", - "itemType": "Item Type", - "relatedTo": "Related To", - "requestDate": "Request Date", - "analyzedDate": "Analyzed Date", - "urgent": "Urgent", - "requestDetails": "Request Details", - "approvalLevel": "Approval Level", - "requesterDetails": "Requester Details", - "myAttendance": "My Attendance", - "workOnBreak": "Work On Break", - "next": "Next", - "apply": "Apply", - "mobile": "Mobile", - "year": "Year", - "month": "Month", - "day": "Day", - "completingYear": "We appreciate you for completing the service of", - "address": "Address", - "phoneNumber": "Phone Number", - "businessGroup": "Business", - "Payroll": "Payroll", - "civilIdentityNumber": "Civil Identity Number", - "dateOfBirth": "Date of Birth", - "maritalStatus ": "Marital Status ", - "fullName": "Full Name", - "remove": "Remove", - "Attendance": "Attendance", - "submit": "Submit", - "areYouSureYouWantToSubmit": "Are you sure you want to submit?", - "comments": "Comments", - "writeComment": "Write a comment", - "approversList": "Approvers List", - "yourRequestHasBeenSubmittedForApprovals": "Your request has been submitted for approvals", - "monthlyPaySlip": "Monthly Pay Slip", - "particular": "Particular", - "earnings": "Earnings", - "deductions": "Deductions", - "paymentMethodName": "Payment Method Name", - "bankName": "Bank Name", - "branchCode": "Branch Code", - "accountNo": "Account No", - "summaryOfInformation": "Summary of Information", - "totalPayAmount": "Total Pay Amount", - "paymentInformation": "Payment Information", - "amount": "Amount", - "correctCurrentDatails": "correct or complete the current details", - "selectType": "Select the type of change you want to make", - "enterNewInfo": "Enter new Information because of a real change to the current details (e.g because of a change in marital status)", - "endDate": "*End Date", - "removeThisMember": "Are You Sure You Want to Remove this Member?", - "wantUpdateThisMember": "Are You Sure You Want to Update this Member?", - "addNewFamilyMember": "Add New Family Member", - "addRow": "Add new row", - "pleaseSelect": "Please Select *", - "delete": "delete", - "add": "Add", - "edit": "Edit", - "myProfile": "My Profile", - "mowadhafhi": "Mowadhafi", - "searchAnnouncements": "Search Announcements", - "announcements": "Announcements", - "swipeRequest": "Swipe Request", - "serviceType": "Service Type", - "departmentName": "Department Name", - "selectDepartment": "Select Department", - "relatedSection": "Related Section", - "selectSection": "Select Section", - "relatedTopic": "Related Topic", - "selectTopic": "Select Topic", - "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafi Request", - "ticketReference": "Ticket Reference", - "section": "Section", - "topic": "Topic", - "actionBy": "Action By", - "pendingTransactions": "Pending Transactions", - "selectRequestType": "Please select request type", - "dateFrom": "Date From", - "dateTo": "Date To", - "requestName": "Request Name", - "createdFor": "Created For", - "requestType": "Request Type", - "requestCreatedSuccessfully": "Request created successfully", - "search": "Search", - "wantToReject": "Are you sure want to reject?", - "employeeDigitalID": "Employee Digital ID", - "businessCard": "Business Card", - "checkOut": "Check Out", - "regular": "Regular", - "mark": "Mark", - "performance": "Performance Evaluation", - "performanceEvaluationIn": "Your performance Evaluation in", - "valuationIn": "Performance Evaluation in", - "viewBusinessCard": "View Business Card", - "performanceEvaluation": "Performance Evaluation", - "logout": "Logout", - "selectMethodOfAttendance": "Select the method to mark the attendance", - "comeNearHMGWifi": "Please come near to HMG wifi", - "deliverNotificationToMeRegardless": "Deliver notifications to me regardless of any general rules", - "close": "Close", - "respond": "Respond", - "vacationRuleAdded": "Vacation rule added", - "selectTypeT": "Select Type", - "notification": "Notification", - "selectNotification": "Select Notification", - "ifAllSelectedYouWillSkip": "*If All is selected, you will skip to step 3", - "applyForVacationRule": "Apply for Vacation Rule", - "step1": "Step 1", - "step2": "Step 2", - "step3": "Step 3", - "message": "Message", - "writeAMessage": "Write a message", - "notificationReassign": "Notification Reassign", - "selectEmployee": "Select Employee", - "searchEmployeeForReplacement": "Search employee for replacement", - "searchForEmployee": "Search for Employee", - "pleaseSpecifyEndTime": "Please specify End Time", - "pleaseSelectNotificationReassign": "Please select notification reassign", - "pleaseSelectEmployeeForReplacement": "Please select employee for replacement", - "pleaseSelectAction": "Please select action", - "pleaseSelectDate": "Please select date", - "todayAttendance": "Today's Attendance", - "viewAttendance": "View Attendance", - "teamMembers": "Team Members", - "profileDetails": "Profile Details", - "noResultsFound": "No Results Found", - "searchBy": "Search by", - "myTeamMembers": "My Team Members", - "save": "Save", - "TurnNotificationsFor": "Turn on notifications for", - "worklistSettings": "Worklist Settings", - "absenceType": "Absence Type", - "absenceCategory": "Absence Category", - "days": "Days", - "hours": "Hours", - "approvalStatus": "Approval Status", - "absenceStatus": "Absence Status", - "poweredBy": "Powered By", - "cloudSolutions": "Cloud Solutions", - "subordinateLeave": "Subordinate Leave", - "numberDays": "Number of days", - "selectTemplate": "Select Template", - "myPostedAds": "My posted ads", - "browseCategories": "Browse Categories", - "searchItems": "Search Items", - "offerAndDiscounts": "Offer & Discounts", - "offerValid": "Offer Valid", - "offerExpired": "Offer Expired", - "whatAreYouOffering": "What are you offering?", - "selectCategory": "Select Category", - "inProgress": "InProgress", - "locked": "Locked", - "addDetails": "Add Details", - "reviewAndSell": "Review & Sell", - "itemTitle": "Item Title", - "itemCondition": "Item Condition", - "used": "Used", - "region": "Region", - "selectRegion": "Select Region", - "itemPrice": "Item Price", - "itemPhotos": "Item Photos", - "itemInfo": "Item Info", - "uploadAttachment": "Upload Attachment", - "selectFromGalleryOrOpenCamera": "Select from gallery or open camera", - "openCamera": "Open\nCamera", - "uploadFromGallery": "Upload from\nGallery", - "name": "Name", - "email": "Email", - "noHistoryAvailable": "No History Available", - "purchaseRequisition": "Purchase Requisition", - "moveOrder": "Move Order", - "humanResource": "Human Resource", - "purchaseOrder": "Purchase Order", - "ITGForms": "ITG Forms", - "itemCreation": "Item Creation", - "stamp": "Stamp", - "addFavoriteList": "Do you want to add {name} in your favorite list", - "feedbackUserExperience": "This is to get the feedback about the user experience", - "rateUI": "How would you like to rate", - "rateUI2": "How do you satisfied with this application", - "submitSurvey": "Submit Survey", - "typeHere": "Type here", - "infoDetail": "Info Detail", - "amount_detail": "Amount Detail", - "currentBalance": "Current Balance", - "currentLeaveBalance": "Current Leave Balance", - "calculatedDays": "Calculated Days", - "totalDays": "Total Days", - "usedBalance": "Used", - "infants": "Infants", - "child": "Child", - "adult": "Adult", - "updateMember": "Are You Sure You Want to Update this Member?", - "fieldIsEmpty": "'{data}' Field is empty. Please select", - "pleaseEnterComments": "Please enter comments", - "skip": "Skip", - "typeCurrentPasswordBelow": "Type Your Current password below", - "currentPassword": "Current password", - "concurrentReports": "Concurrent Reports", - "EnterNewAddressMoved": "Enter a new address if you have moved", - "CorrectAddress": "Correct or amend this address", - "SelectChangeWantToMake": "Select the type of change you want to make", - "profile": { - "reset_password": { - "label": "Reset Password", - "username": "Username", - "password": "password" + "phoneNumber": "رقم الجوال", + "businessGroup": "مجموعة العمل", + "Payroll": "الراتب", + "civilIdentityNumber": "رقم الهويه", + "dateOfBirth": "تاريخ الميلاد", + "maritalStatus ": "الحالة الاجتماعية", + "fullName": "الأسم الكامل", + "remove": "حذف", + "submit": "ارسال", + "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", + "comments": "تعليقات", + "writeComment": "أكتب تعليقا", + "approversList": "قائمة الموافقين", + "yourRequestHasBeenSubmittedForApprovals": "تم تقديم طلبك للموافقات", + "monthlyPaySlip": "قسيمة الراتب الشهرية", + "particular": "خاص", + "earnings": "أرباح", + "deductions": "الخصومات", + "paymentMethodName": "اسم طريقة الدفع", + "bankName": "اسم البنك", + "branchCode": "رمز الفرع", + "accountNo": "رقم الحساب", + "summaryOfInformation": "ملخص المعلومات", + "totalPayAmount": "المبلغ الإجمالي للدفع", + "paymentInformation": "معلومات الدفع", + "performance": "تقييم الاداء", + "performanceEvaluation": "تقييم الأداء في", + "performanceEvaluationIn": "تقييم أدائك في", + "valuationIn": "تقييم الأداء في", + "amount": "مقدار", + "correctCurrentDatails": "تعديل او اكمال التفاصيل الحالية", + "selectType": " حدد نوع التغيير الذي تريد القيام به", + "enterNewInfo": " أدخل معلومات جديدة بسبب تغيير حقيقي في التفاصيل الحالية (على سبيل المثال بسبب تغيير في الحالة الاجتماعية", + "endDate": "تاريخ الانتهاء", + "removeThisMember": "هل انت متأكد تريد ازالة هذا العضو؟", + "wantUpdateThisMember ": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", + "addNewFamilyMember": "اضافة عضو جديد", + "addRow": "اضافة صف جديد", + "pleaseSelect": "الرجاء اختيار", + "delete": "حذف", + "edit": "تعديل", + "add": "اضافه", + "myProfile": "معلوماتي", + "mowadhafhi": "موظفي", + "searchAnnouncements": "بحث الاعلانات", + "announcements": "اعلانات", + "swipeRequest": "طلب تسجيل حضور", + "serviceType": "نوع الخدمه", + "departmentName": "اسم القسم", + "selectDepartment": "اختر القسم", + "relatedSection": "قسم ذو صله", + "selectSection": "اختيار القسم", + "relatedTopic": "عنوان ذو صله", + "selectTopic": "اختر العنوان", + "supportingDocument": "ارفاق مستند", + "mowadhafhiRequest": "طلب موظفي", + "ticketReference": "مرجع التذكره", + "section": "القسم", + "topic": "العنوان", + "actionBy": "الرد بواسطة", + "pending": "معلق", + "pendingTransactions": "المعاملات المعلقه", + "selectRequestType": "الرجاء اختيار نوع الطلب", + "dateFrom": "من تاريخ", + "dateTo": "الى تاريخ", + "requestName": "اسم الطلب", + "createdFor": "انشاء لأجل", + "requestCreatedSuccessfully": "تم انشاء الطلب بنجاح", + "search": "بحث", + "wantToReject": "هل انت متأكد تريد الرفض", + "requestType": "نوع الطلب", + "employeeDigitalID": "هويةالموظف الرقمية", + "businessCard": "بطاقة العمل", + "viewBusinessCard": "عرض بطاقة العمل", + "logout": "تسجيل خروج", + "checkOut": "وقت الخروج", + "regular": "منتظم", + "mark": "علامة", + "selectMethodOfAttendance": "اختر طريقة تسجيل الحضور", + "comeNearHMGWifi": "HMG wifi من فضلك اقترب من", + "deliverNotificationToMeRegardless": "تسليم الإخطارات إلي بغض النظر عن أي قواعد عامة", + "close": "أغلق", + "respond": "يرد", + "vacationRuleAdded": "تمت إضافة قاعدة الإجازة", + "selectTypeT": "اختر صنف", + "notification": "تنبيه", + "selectNotification": "حدد إعلام", + "ifAllSelectedYouWillSkip": "* إذا تم تحديد الكل ، فستنتقل إلى الخطوة 3", + "applyForVacationRule": "التقدم بطلب للحصول على قانون الإجازة", + "step1": "الخطوة 1", + "step2": "الخطوة 2", + "step3": "الخطوه 3", + "message": "رسالة", + "writeAMessage": "اكتب رسالة", + "notificationReassign": "إعادة تعيين الإخطار", + "selectEmployee": "حدد الموظف", + "searchEmployeeForReplacement": "ابحث عن موظف بديل", + "searchForEmployee": "ابحث عن موظف", + "pleaseSpecifyEndTime": "الرجاء تحديد وقت الانتهاء", + "pleaseSelectNotificationReassign": "يرجى تحديد إعادة تعيين الإخطار", + "pleaseSelectEmployeeForReplacement": "الرجاء تحديد موظف للاستبدال", + "pleaseSelectAction": "الرجاء تحديد الإجراء", + "pleaseSelectDate": "الرجاء تحديد التاريخ", + "todayAttendance": "حضور اليوم", + "viewAttendance": "عرض الحضور", + "teamMembers": "اعضاءالفريق", + "profileDetails": "الملف الشخصي", + "noResultsFound": "لايوجد نتائج", + "searchBy": "بحث بواسطة", + "myTeamMembers": "اعضاء فريقي", + "save": "حفظ", + "TurnNotificationsFor": "تفعيل الاشعارات", + "worklistSettings": "اعدادات الاشعارات", + "absenceType": "نوع الغياب", + "absenceCategory": "فئة الغياب", + "days": "أيام", + "hours": "ساعات", + "approvalStatus": "حالة القبول", + "absenceStatus": "حالة الغياب", + "subordinateLeave": "إجازة التابعيين", + "numberDays": "عدد الأيام", + "poweredBy": "مشغل بواسطة", + "cloudSolutions": "حلول السحابة", + "selectTemplate": "حدد قالب", + "myPostedAds": "إعلاناتي المنشورة", + "browseCategories": "تصفح الفئات", + "searchItems": "عناصر البحث", + "offerAndDiscounts": "العروض والخصومات", + "offerValid": "العرض صالح", + "offerExpired": "انتهى العرض", + "whatAreYouOffering": "ما الذي تعرضه؟", + "selectCategory": "اختر الفئة", + "inProgress": "في تَقَدم", + "locked": "مقفل", + "addDetails": "أضف التفاصيل", + "reviewAndSell": "مراجعة وبيع", + "itemTitle": "عنوان البند", + "itemCondition": "حالة السلعة", + "used": "تستخدم", + "region": "منطقة", + "selectRegion": "اختر المنطقة", + "itemPrice": "سعر السلعة", + "itemPhotos": "صور البند", + "itemInfo": "معلومات العنصر", + "uploadAttachment": "تحميل المرفق", + "selectFromGalleryOrOpenCamera": "اختر من المعرض أو فتح الكاميرا", + "openCamera": "فتح\nالكاميرا", + "uploadFromGallery": "تحميل من\nملفات الجهاز", + "name": "الأسم", + "email": "ايميل", + "noHistoryAvailable": "لايوجد سجل بيانات سابقة ", + "purchaseRequisition": "طلب شراء", + "moveOrder": "طلب تغيير", + "humanResource": "الموارد البشريه", + "purchaseOrder": "امر شراء", + "ITGForms": "ITG نماذج", + "itemCreation": "أنشاء عنصر", + "stamp": "ختم", + "addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله", + "feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم", + "rateUI": "كيف تريد أن تقيم", + "rateUI2": "ما مدى رضائك عن هذا التطبيق", + "submitSurvey": "ارسال الاستبيان", + "typeHere": "اكتب هنا", + "infoDetail": "تفاصيل المعلومات", + "amount_detail": "تفاصيل المبلغ", + "currentBalance": "الرصيد الحالي", + "currentLeaveBalance": "رصيد الاجازات الحالي", + "calculatedDays": "الايام المحسوبه", + "totalDays": "مجموع الأيام", + "usedBalance": "المستخدم", + "infants": "رضيع", + "child": "طفل", + "adult": "بالغ", + "updateMember": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", + "fieldIsEmpty": "'{data}' الحقل فارغ. الرجاء التحديد", + "pleaseEnterComments": "الرجاء إدخال التعليقات", + "skip": "يتخطى", + "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", + "currentPassword": "كلمة المرور الحاليه", + "concurrentReports": "التقارير المتزامنه", + "EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت", + "CorrectAddress": "تصحيح أو تعديل هذا العنوان", + "SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.", + "profile": { + "reset_password": {"label": "Reset Password", "username": "Username", "password": "password"}, + "profileCompletionPer": "استكمال الملف الشخصي", + "completeProfile": "الملف الشخصي الكامل", + "personalInformation": "معلومات شخصية", + "basicDetails": "تفاصيل أساسية", + "address": "العنوان", + "contactDetails": "بيانات التواصل", + "familyDetails": "تفاصيل عائلية", + "effectiveDate": "تاريخ النفاذ", + "country": "دولة" + }, + "clicked": { + "zero": "You clicked {} times!", + "one": "You clicked {} time!", + "two": "You clicked {} times!", + "few": "You clicked {} times!", + "many": "You clicked {} times!", + "other": "You clicked {} times!" + }, + "gender": { + "male": "Hi man ;) ", + "female": "Hello girl :)", + "with_arg": {"male": "Hi man ;) {}", "female": "Hello girl :) {}"} }, - "profileCompletionPer": "Profile Completion", - "completeProfile": "Complete Profile", - "personalInformation": "Personal Information", - "basicDetails": "Basic Details", + "reset_locale": "إعادة ضبط اللغة", + "chat": "دردشة", + "mychats": "دردشاتي", + "advancedSearch": "بحث متقدم", + "openNot": "التبليغات المفتوحة", + "fyi": "تبليغات للعلم", + "toDo": "تبليغات الأعمال", + "all": "كل التبليغات", + "meNot": "تبليغات صادرة مني", + "view": "عرض", + "fromUserName": "من", + "sentDate": "تاريخ الإرسال", + "itemTypeDisplayName": "اسم العرض", + "none": "بدون", + "createNewChat": "إنشاء محادثة جديدة", + "brainMarathon": "ماراثون الدماغ", + "contestTopicAbout": "سيكون موضوع المسابقة حول:", + "gameDate": "تاريخ اللعبة:", + "gameTime": "وقت اللعب:", + "joinMarathon": "انضم إلى ماراثون", + "joinDemoMarathon": "انضم إلى الماراثون التجريبي", + "demo": "تجريبي", + "minutes": "الدقائق", + "seconds": "ثواني", + "note": "ملحوظة:", + "demoMarathonNoteP1": "يمكنك لعب ماراثون العرض لتتعلم كيف يعمل. يمكنك الانضمام إلى ماراثون", + "demoMarathonNoteP2": "خمس دقائق", + "demoMarathonNoteP3": "قبل الوقت الفعلي.", + "sponsoredBy": "برعاية:", + "question": "سؤال", + "marathoners": "الماراثون", + "marathoner": "ماراثونر", + "prize": "جائزة:", + "winnerSelection": "اختيار الفائز", + "qualifiers": "تصفيات", + "qualifier": "المؤهل", + "getReadyForContest": "استعد للمسابقة القادمة:", + "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", + "fingersCrossed": "تشابك الاصابع!!!", + "congrats": "مبروك !!!", + "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", + "otp": "OTP", + "verification": "تَحَقّق", + "resend": "إعادة إرسال", + "codeExpire": "انتهت صلاحية رمز التحقق", + "typeheretoreply": "اكتب هنا للرد", + "favorite": "مفضلتي", + "searchfromchat": "البحث من الدردشة", + "yourAnswerCorrect": "إجابتك صحيحة", + "youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "oops": "أوه!!!", + "winner": "الفائز", + "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", + "ourSponsor": "راعينا:", + "startingIn": "يبدأ في", + "youAreOutOfContest": "أنت خارج المسابقة.", + "winners": "الفائزين!!!", + "expireAfter": "تنتهي بعد", + "oneWeek": "أسبوع 1", + "twoWeek": "2 أسبوع", + "noUpcoming": "لا يوجد قادم", + "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", + "noWinner": "حزين! لم يفز أحد اليوم.", + "myTeam": "فريقي", + "youCanPlayDemo": "لكن يمكنك لعب العرض", + "group": "مجموعة", + "searchGroup": "مجموعة البحث", + "connectHmgWifi": "قم بتوصيل HMG WIFI", + "connectedHmgWifi": "اتصال HMG WIFI", + "itgForms": "نماذج (ITG)", + "resetAdPassword": "إعادة تعيين كلمة مرور AD", + "myDocuments": "مستنداتي", + "requiredDocuments": "المستندات المطلوبة", + "optionalDocuments": "المستندات الاختيارية", + "allDocuments": "كافة المستندات", + "expiredDocuments": "المستندات منتهية الصلاحية", + "missingDocuments": "مستندات مفقودة", + "uploadedDocuments": "المستندات التي تم تحميلها", + "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني", + "pleaseClickButtonToJoinMarathon": "الرجاء الضغط على الزر أدناه للانضمام إلى الماراثون", + }; + static const Map en_US = { + "mohemm": "Mohemm", + "english": "English", + "arabic": "عربي", + "login": "Login", + "pleaseEnterLoginDetails": "Please enter the detail below to login", + "username": "Username", + "password": "Password", + "welcomeBack": "Welcome back", + "wouldYouLikeToLoginWithCurrentUsername": "Would you like to login with current Username?", + "lastLoginDetails": "Last Login Details:", + "verificationType": "Verification Type:", + "pleaseVerify": "Please Verify", + "pleaseVerifyForBio": "Please verify login with one of the following options", + "verifyThroughFace": "Verify Through Face", + "verifyThroughFingerprint": "Verify Through Fingerprint", + "verifyThroughSMS": "Verify Through SMS", + "verifyThroughWhatsapp": "Verify Through Whatsapp", + "useAnotherAccount": "Use Another Account", + "pleaseEnterTheVerificationCodeSentTo": "Please enter the verification code sent to ", + "theVerificationCodeWillExpireIn": "The verification code will expire in ", + "goodMorning": "Good Morning", + "markAttendance": "Mark Attendance", + "timeLeftToday": "Time Left Today", + "checkIn": "Check In", + "workList": "Work List", + "leaveBalance": "Leave Balance", + "missingSwipes": "Missing Swipes", + "ticketBalance": "Ticket Balance", + "other": "Other", + "services": "Services", + "viewAllServices": "View All Services", + "monthlyAttendance": "Monthly Attendance", + "vacationRule": "Vacation Rule", + "vacationType": "Vacation Type", + "startDateT": "Start Date", + "endDateT": "End Date", + "workFromHome": "Work From Home", + "ticketRequest": "Ticket Request", + "viewAllOffers": "View All Offers", + "offers": "Offers & ", + "discounts": "Discounts", + "newString": "New", + "setTheNewPassword": "Set the new password", + "typeYourNewPasswordBelow": "Type your new password below", + "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", + "confirmPassword": "Confirm Password", + "update": "Update", + "title": "Title", + "home": "Home", + "mySalary": "My Salary", + "createRequest": "Create Request", + "forgotPassword": "Forgot Password", + "employeeId": "Employee ID", + "loginCodeWillSentToMobileNumber": "Please Enter your Employee ID, A login code will be sent to your mobile number", + "changePassword": "Change Password", + "ok": "OK", + "confirm": "Confirm", + "passwordChangedSuccessfully": "Password changed successfully", + "itemsForSale": "Items for Sale", + "attendanceDetails": "Attendance Details", + "order": "order", + "earlyOut": "Early Out", + "shortage": "Shortage", + "excess": "Excess", + "lateIn": "Late In", + "approvedCheckOut": "Approved Check Out", + "approvedCheckIn": "Approved Check In", + "actualCheckOut": "Actual Check Out", + "actualCheckIn": "Actual Check In", + "present": "PRESENT", + "pres": "present", + "shiftTime": "Shift Time", + "absent": "ABSENT", + "attendance": "Attendance", + "scheduleDays": "Schedule\nDays", + "offDays": "Off\nDays", + "nonAnalyzed": "Non\nAnalyzed", + "shortageHour": "Shortage\nHour", + "stats": "Stats", + "completed": "Completed", + "doNotUseRecentPassword": "Do not use recent password", + "atLeastOneLowercase": "At least one lowercase", + "atLeastOneUppercase": "At least one uppercase", + "atLeastOneNumeric": "At least one numeric", + "minimum8Characters": "Minimum 8 characters", + "doNotAddRepeatingLetters": "Do not add repeating letters", + "itShouldContainSpecialCharacter": "It should contain special character", + "confirmPasswordMustMatch": "Confirm password must match", + "sms": "SMS", + "fingerPrint": "Fingerprint", + "face": "Face", + "whatsapp": "Whatsapp", + "reject": "Reject", + "approve": "Approve", + "cancel": "Cancel", + "requestedItems": "Requested Items", + "request": "Request", + "myRequest": "My Request", + "actions": "Actions", + "delegate": "Delegate", + "request_info": "Request Info", + "attachments": "Attachments", + "info": "Info.", + "employeeNumber": "Employee Number", + "assignmentNumber": "Assignment Number", + "employeeName": "Employee Name", + "scheduleDate": "Schedule Date", + "shiftType": "Shift Type", + "shift": "Shift", + "breakText": "Break", + "actualSwipeStart": "Actual Swipe Start", + "actualSwipeEnd": "Actual Swipe End", + "approvedSwipeStart": "Approved Swipe Start", + "approvedSwipeStartReason": "Approved Swipe Start Reason", + "approvedSwipeEnd": "Approved Swipe End", + "approvedSwipeEndReason": "Approved Swipe End Reason", + "from": "From", + "to": "To", + "sent": "Sent", + "closed": "Closed", + "id": "ID", + "responder": "Responder", + "jobTitle": "Job Title", + "grade": "Grade", + "jobCategory": "Job Category", + "category": "Category", + "employeeEmailAddress": "Employee Email Address", + "payrollBranch": "Payroll Branch", + "yourChangeHasBeenSavedSuccessfully": "Your change has been saved successfully", + "code": "Code", + "unit": "Unit", + "quantity": "Quantity", + "dateRequired": "Date Required", + "lineStatus": "Line Status", + "statusDate": "Status Date", + "transactionType": "Transaction Type", + "operatingUnit": "Operating Unit", + "organizationCode": "Organization Code", + "organization": "Organization", + "fromSubInventory": "From Sub Inventory", + "fromLocator": "From Locator", + "toSubInventory": "To Sub Inventory", + "toLocator": "To Locator", + "shipToLocator": "Ship To Locator", + "itemHistory": "Item History", + "mfg": "MFG", + "lineType": "Line Type", + "price": "Price", + "lineAmount": "Line Amount", + "lineDiscount": "Line Discount %", + "needByDate": "Need By Date", + "promisedDate": "Promised Date", + "deliverToLocation": "Deliver To Location", + "requisitionNumber": "Requisition Number", + "requester": "Requester", + "subject": "Subject", + "quotationAnalysis": "Quotation Analysis", + "description": "Description", + "supplier": "Supplier", + "site": "Site", + "buyer": "Buyer", + "preparer": "Preparer", + "creationDate": "Creation Date", + "shipToLocation": "Ship To Location", + "quotationNumber": "Quotation Number", + "quotationDate": "Quotation Date", + "paymentTerms": "Payment Terms", + "currency": "Currency", + "grossAmount": "Gross Amount", + "discountAmount": "Discount Amount", + "customDuty": "Custom Duty", + "shipHandle": "Ship Handle", + "otherCharges": "Other Charges", + "totalPOAmountWithVAT": "Total PO Amount With VAT", + "totalPOAmountInWords": "Total PO Amount In Words", + "requestNumber": "Request Number", + "uom": "UOM", + "operatingCode": "Operating Code", + "poNumber": "PO Number", + "revision": "Revision", + "quantityOrdered": "Quantity Ordered", + "quantityReceived": "Quantity Received", + "bonusQuantity": "Bonus Quantity", + "purchasePrice": "Purchase Price", + "discountPer": "Discount %", + "balanceQuantity": "Balance Quantity", + "netPrice": "Net Price", + "closureStatus": "Closure Status", + "quotationNetPrice": "Quotation Net Price", + "quotationUOM": "Quotation UOM", + "quotationQty": "Quotation Qty", + "itemCode": "item Code", + "vendorName": "Vendor Name", + "quotationMFGPartNumber": "Quotation MFG Part Number", + "quotationDeliveryDate": "Quotation Delivery Date", + "quotationBonusQuantity": "Quotation Bonus Quantity", + "quotationLineTotal": "Quotation Line Total", + "rfqUOM": "RFQ UOM", + "rfqQty": "RFQ Qty", + "rfqNumber": "RFQ Number", + "msg": "Hello {} in the {} world ", + "msg_named": "{} are written in the {lang} language", + "clickMe": "Click me", + "human": "Human", + "resources": "Resources", + "details": "Details", + "noDataAvailable": "No Data Available", + "productName": "Product Name", + "productDescription": "Product Description", + "unitPrice": "Unit Price", + "manufacturerName": "Manufacturer Name", + "manufacturerPartName": "Manufacturer Part Name", + "supplierName": "Supplier Name", + "supplierContact": "Supplier Contact", + "chargeToPatient": "Charge To Patient", + "justification": "Justification", + "itemDescription": "Item Description", + "groupCode": "Group Code", + "primaryUOM": "Primary UOM", + "subgroupDescription": "Subgroup Description", + "subgroupCode": "Subgroup Code", + "groupDescription": "Group Description", + "templateName": "Template Name", + "itemCreationStatus": "Item Creation Status", + "standardizationApprovalStatus": "Standardization Approval Status", + "standardizationApprovalRejectionReason": "Standardization Approval Rejection Reason", + "analyzedBy": "Analyzed By", + "approvedDate": "Approved Date", + "itemType": "Item Type", + "relatedTo": "Related To", + "requestDate": "Request Date", + "analyzedDate": "Analyzed Date", + "urgent": "Urgent", + "requestDetails": "Request Details", + "approvalLevel": "Approval Level", + "requesterDetails": "Requester Details", + "myAttendance": "My Attendance", + "workOnBreak": "Work On Break", + "next": "Next", + "apply": "Apply", + "mobile": "Mobile", + "year": "Year", + "month": "Month", + "day": "Day", + "completingYear": "We appreciate you for completing the service of", "address": "Address", - "contactDetails": "Contact Details", - "familyDetails": "Family Members", - "effectiveDate": "Effective Date", - "country": "Country" - }, - "clicked": { - "zero": "You clicked {} times!", - "one": "You clicked {} time!", - "two": "You clicked {} times!", - "few": "You clicked {} times!", - "many": "You clicked {} times!", - "other": "You clicked {} times!" - }, - "gender": { - "male": "Hi man ;) ", - "female": "Hello girl :)", - "with_arg": { - "male": "Hi man ;) {}", - "female": "Hello girl :) {}" - } - }, - "reset_locale": "Reset Language", - "chat": "Chat", - "mychats": "My Chats", - "createNewChat": "Create New Chat", - "brainMarathon": "Brain Marathon", - "contestTopicAbout": "Contest Topic will be about:", - "gameDate": "Game Date:", - "gameTime": "Game Time:", - "joinMarathon": "Join Marathon", - "joinDemoMarathon": "Join Demo Marathon", - "demo": "Demo", - "minutes": "Minutes", - "seconds": "Seconds", - "note": "Note:", - "demoMarathonNoteP1": "You can play the demo Marathon to learn how it works. You can join the Marathon", - "demoMarathonNoteP2": "5 Minutes", - "demoMarathonNoteP3": "before the actual time.", - "sponsoredBy": "Sponsored By:", - "question": "Question", - "marathoners": "Marathoners", - "marathoner": "Marathoner", - "prize": "Prize:", - "advancedSearch": "Advanced Search", - "openNot": "Open Notifications", - "fyi": "FYI Notifications", - "toDo": "To Do Notifications", - "all": "All Notifications", - "meNot": "Notifications from Me", - "view": "View", - "fromUserName": "From User Name", - "sentDate": "Sent Date", - "itemTypeDisplayName": "Item Type Display Name", - "none": "None", - "winnerSelection": "Winner Selection", - "qualifiers": "Qualifiers", - "qualifier": "Qualifier", - "getReadyForContest": "Get Ready for the coming contest:", - "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", - "fingersCrossed": "Fingers Crossed!!!", - "congrats": "Congratulations!!!", - "otp": "OTP", - "verification": "Verification", - "resend": "Resend", - "codeExpire": "The verification code has been expired", - "allQuestionsCorrect": "You have answered all questions correct", - "typeheretoreply": "Type here to reply", - "favorite": "My Favorites", - "searchfromchat": "Search from chat", - "yourAnswerCorrect": "Your answer is correct", - "youMissedTheQuestion": "You ran out of time. You are out of the game. But you can continue as a viewer.", - "wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue as a viewer.", - "oops": "Ooopsss!!!!", - "winner": "WINNER", - "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", - "ourSponsor": "Our Sponsor:", - "startingIn": "Starting in", - "youAreOutOfContest": "You are out of the contest.", - "winners": "WINNERS!!!", - "expireAfter": "Expires After", - "oneWeek": "1 Week", - "twoWeek": "2 Week", - "noUpcoming": "There is no upcoming", - "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", - "noWinner": "Sad! No one won today.", - "myTeam": "My Team", - "youCanPlayDemo": "But you can play demo", - "connectHmgWifi": "Connect HMG WIFI", - "connectedHmgWifi": "Connected HMG WIFI", - "itgForms": "ITG Forms", - "resetAdPassword": "Reset AD Password", - "myDocuments": "My Documents", - "requiredDocuments": "Required Documents", - "optionalDocuments": "Optional Documents", - "allDocuments": "All\nDocuments", - "expiredDocuments": "Expired\nDocuments", - "missingDocuments": "Missing\nDocuments", - "uploadedDocuments": "Uploaded\nDocuments" -}; -static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; + "phoneNumber": "Phone Number", + "businessGroup": "Business", + "Payroll": "Payroll", + "civilIdentityNumber": "Civil Identity Number", + "dateOfBirth": "Date of Birth", + "maritalStatus ": "Marital Status ", + "fullName": "Full Name", + "remove": "Remove", + "Attendance": "Attendance", + "submit": "Submit", + "areYouSureYouWantToSubmit": "Are you sure you want to submit?", + "comments": "Comments", + "writeComment": "Write a comment", + "approversList": "Approvers List", + "yourRequestHasBeenSubmittedForApprovals": "Your request has been submitted for approvals", + "monthlyPaySlip": "Monthly Pay Slip", + "particular": "Particular", + "earnings": "Earnings", + "deductions": "Deductions", + "paymentMethodName": "Payment Method Name", + "bankName": "Bank Name", + "branchCode": "Branch Code", + "accountNo": "Account No", + "summaryOfInformation": "Summary of Information", + "totalPayAmount": "Total Pay Amount", + "paymentInformation": "Payment Information", + "amount": "Amount", + "correctCurrentDatails": "correct or complete the current details", + "selectType": "Select the type of change you want to make", + "enterNewInfo": "Enter new Information because of a real change to the current details (e.g because of a change in marital status)", + "endDate": "*End Date", + "removeThisMember": "Are You Sure You Want to Remove this Member?", + "wantUpdateThisMember": "Are You Sure You Want to Update this Member?", + "addNewFamilyMember": "Add New Family Member", + "addRow": "Add new row", + "pleaseSelect": "Please Select *", + "delete": "delete", + "add": "Add", + "edit": "Edit", + "myProfile": "My Profile", + "mowadhafhi": "Mowadhafi", + "searchAnnouncements": "Search Announcements", + "announcements": "Announcements", + "swipeRequest": "Swipe Request", + "serviceType": "Service Type", + "departmentName": "Department Name", + "selectDepartment": "Select Department", + "relatedSection": "Related Section", + "selectSection": "Select Section", + "relatedTopic": "Related Topic", + "selectTopic": "Select Topic", + "supportingDocument": "Supporting Document", + "mowadhafhiRequest": "Mowadhafi Request", + "ticketReference": "Ticket Reference", + "section": "Section", + "topic": "Topic", + "actionBy": "Action By", + "pendingTransactions": "Pending Transactions", + "selectRequestType": "Please select request type", + "dateFrom": "Date From", + "dateTo": "Date To", + "requestName": "Request Name", + "createdFor": "Created For", + "requestType": "Request Type", + "requestCreatedSuccessfully": "Request created successfully", + "search": "Search", + "wantToReject": "Are you sure want to reject?", + "employeeDigitalID": "Employee Digital ID", + "businessCard": "Business Card", + "checkOut": "Check Out", + "regular": "Regular", + "mark": "Mark", + "performance": "Performance Evaluation", + "performanceEvaluationIn": "Your performance Evaluation in", + "valuationIn": "Performance Evaluation in", + "viewBusinessCard": "View Business Card", + "performanceEvaluation": "Performance Evaluation", + "logout": "Logout", + "selectMethodOfAttendance": "Select the method to mark the attendance", + "comeNearHMGWifi": "Please come near to HMG wifi", + "deliverNotificationToMeRegardless": "Deliver notifications to me regardless of any general rules", + "close": "Close", + "respond": "Respond", + "vacationRuleAdded": "Vacation rule added", + "selectTypeT": "Select Type", + "notification": "Notification", + "selectNotification": "Select Notification", + "ifAllSelectedYouWillSkip": "*If All is selected, you will skip to step 3", + "applyForVacationRule": "Apply for Vacation Rule", + "step1": "Step 1", + "step2": "Step 2", + "step3": "Step 3", + "message": "Message", + "writeAMessage": "Write a message", + "notificationReassign": "Notification Reassign", + "selectEmployee": "Select Employee", + "searchEmployeeForReplacement": "Search employee for replacement", + "searchForEmployee": "Search for Employee", + "pleaseSpecifyEndTime": "Please specify End Time", + "pleaseSelectNotificationReassign": "Please select notification reassign", + "pleaseSelectEmployeeForReplacement": "Please select employee for replacement", + "pleaseSelectAction": "Please select action", + "pleaseSelectDate": "Please select date", + "todayAttendance": "Today's Attendance", + "viewAttendance": "View Attendance", + "teamMembers": "Team Members", + "profileDetails": "Profile Details", + "noResultsFound": "No Results Found", + "searchBy": "Search by", + "myTeamMembers": "My Team Members", + "save": "Save", + "TurnNotificationsFor": "Turn on notifications for", + "worklistSettings": "Worklist Settings", + "absenceType": "Absence Type", + "absenceCategory": "Absence Category", + "days": "Days", + "hours": "Hours", + "approvalStatus": "Approval Status", + "absenceStatus": "Absence Status", + "poweredBy": "Powered By", + "cloudSolutions": "Cloud Solutions", + "subordinateLeave": "Subordinate Leave", + "numberDays": "Number of days", + "selectTemplate": "Select Template", + "myPostedAds": "My posted ads", + "browseCategories": "Browse Categories", + "searchItems": "Search Items", + "offerAndDiscounts": "Offer & Discounts", + "offerValid": "Offer Valid", + "offerExpired": "Offer Expired", + "whatAreYouOffering": "What are you offering?", + "selectCategory": "Select Category", + "inProgress": "InProgress", + "locked": "Locked", + "addDetails": "Add Details", + "reviewAndSell": "Review & Sell", + "itemTitle": "Item Title", + "itemCondition": "Item Condition", + "used": "Used", + "region": "Region", + "selectRegion": "Select Region", + "itemPrice": "Item Price", + "itemPhotos": "Item Photos", + "itemInfo": "Item Info", + "uploadAttachment": "Upload Attachment", + "selectFromGalleryOrOpenCamera": "Select from gallery or open camera", + "openCamera": "Open\nCamera", + "uploadFromGallery": "Upload from\nGallery", + "name": "Name", + "email": "Email", + "noHistoryAvailable": "No History Available", + "purchaseRequisition": "Purchase Requisition", + "moveOrder": "Move Order", + "humanResource": "Human Resource", + "purchaseOrder": "Purchase Order", + "ITGForms": "ITG Forms", + "itemCreation": "Item Creation", + "stamp": "Stamp", + "addFavoriteList": "Do you want to add {name} in your favorite list", + "feedbackUserExperience": "This is to get the feedback about the user experience", + "rateUI": "How would you like to rate", + "rateUI2": "How do you satisfied with this application", + "submitSurvey": "Submit Survey", + "typeHere": "Type here", + "infoDetail": "Info Detail", + "amount_detail": "Amount Detail", + "currentBalance": "Current Balance", + "currentLeaveBalance": "Current Leave Balance", + "calculatedDays": "Calculated Days", + "totalDays": "Total Days", + "usedBalance": "Used", + "infants": "Infants", + "child": "Child", + "adult": "Adult", + "updateMember": "Are You Sure You Want to Update this Member?", + "fieldIsEmpty": "'{data}' Field is empty. Please select", + "pleaseEnterComments": "Please enter comments", + "skip": "Skip", + "typeCurrentPasswordBelow": "Type Your Current password below", + "currentPassword": "Current password", + "concurrentReports": "Concurrent Reports", + "EnterNewAddressMoved": "Enter a new address if you have moved", + "CorrectAddress": "Correct or amend this address", + "SelectChangeWantToMake": "Select the type of change you want to make", + "profile": { + "reset_password": {"label": "Reset Password", "username": "Username", "password": "password"}, + "profileCompletionPer": "Profile Completion", + "completeProfile": "Complete Profile", + "personalInformation": "Personal Information", + "basicDetails": "Basic Details", + "address": "Address", + "contactDetails": "Contact Details", + "familyDetails": "Family Members", + "effectiveDate": "Effective Date", + "country": "Country" + }, + "clicked": { + "zero": "You clicked {} times!", + "one": "You clicked {} time!", + "two": "You clicked {} times!", + "few": "You clicked {} times!", + "many": "You clicked {} times!", + "other": "You clicked {} times!" + }, + "gender": { + "male": "Hi man ;) ", + "female": "Hello girl :)", + "with_arg": {"male": "Hi man ;) {}", "female": "Hello girl :) {}"} + }, + "reset_locale": "Reset Language", + "chat": "Chat", + "mychats": "My Chats", + "createNewChat": "Create New Chat", + "brainMarathon": "Brain Marathon", + "contestTopicAbout": "Contest Topic will be about:", + "gameDate": "Game Date:", + "gameTime": "Game Time:", + "joinMarathon": "Join Marathon", + "joinDemoMarathon": "Join Demo Marathon", + "demo": "Demo", + "minutes": "Minutes", + "seconds": "Seconds", + "note": "Note:", + "demoMarathonNoteP1": "You can play the demo Marathon to learn how it works. You can join the Marathon", + "demoMarathonNoteP2": "5 Minutes", + "demoMarathonNoteP3": "before the actual time.", + "sponsoredBy": "Sponsored By:", + "question": "Question", + "marathoners": "Marathoners", + "marathoner": "Marathoner", + "prize": "Prize:", + "advancedSearch": "Advanced Search", + "openNot": "Open Notifications", + "fyi": "FYI Notifications", + "toDo": "To Do Notifications", + "all": "All Notifications", + "meNot": "Notifications from Me", + "view": "View", + "fromUserName": "From User Name", + "sentDate": "Sent Date", + "itemTypeDisplayName": "Item Type Display Name", + "none": "None", + "winnerSelection": "Winner Selection", + "qualifiers": "Qualifiers", + "qualifier": "Qualifier", + "getReadyForContest": "Get Ready for the coming contest:", + "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", + "fingersCrossed": "Fingers Crossed!!!", + "congrats": "Congratulations!!!", + "otp": "OTP", + "verification": "Verification", + "resend": "Resend", + "codeExpire": "The verification code has been expired", + "allQuestionsCorrect": "You have answered all questions correct", + "typeheretoreply": "Type here to reply", + "favorite": "My Favorites", + "searchfromchat": "Search from chat", + "yourAnswerCorrect": "Your answer is correct", + "youMissedTheQuestion": "You ran out of time. You are out of the game. But you can continue as a viewer.", + "wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue as a viewer.", + "oops": "Ooopsss!!!!", + "winner": "WINNER", + "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", + "ourSponsor": "Our Sponsor:", + "startingIn": "Starting in", + "youAreOutOfContest": "You are out of the contest.", + "winners": "WINNERS!!!", + "expireAfter": "Expires After", + "oneWeek": "1 Week", + "twoWeek": "2 Week", + "noUpcoming": "There is no upcoming", + "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", + "noWinner": "Sad! No one won today.", + "myTeam": "My Team", + "youCanPlayDemo": "But you can play demo", + "group": "Groups", + "searchGroup": "Search Group", + "connectHmgWifi": "Connect HMG WIFI", + "connectedHmgWifi": "Connected HMG WIFI", + "itgForms": "ITG Forms", + "resetAdPassword": "Reset AD Password", + "myDocuments": "My Documents", + "requiredDocuments": "Required Documents", + "optionalDocuments": "Optional Documents", + "allDocuments": "All\nDocuments", + "expiredDocuments": "Expired\nDocuments", + "missingDocuments": "Missing\nDocuments", + "uploadedDocuments": "Uploaded\nDocuments", + "manage": "Manage", + "members": "Members", + "areYouSureWantTodelete": "Are you sure want to delete?", + "groupMembers": "Group Members", + "manageGroup": "Manage Group", + "admin": "Admin", + "addUsers": "Add users to the group", + "editGroups": "Edit Group", + "groupNameshouldbe": "Group name should be minimum 10 character long", + "enterGroupName": "Please enter valid group Name", + "groupName": "Group Name", + "enterGroupNamePlease": "Please enter group name", + "audioCall": "Audio Call", + "videoCall": "Video Call", + "shareScreen": "Share Screen", + "searchByUserName": "Search By Username", + "userSearch": "User Search", + "userName": "User Name", + "userId": "UserID", + "pleaseClickButtonToJoinMarathon": "Press the button below to join the Marathon.", + "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit." + }; + static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 3a4921f..7a3501f 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -513,6 +513,8 @@ abstract class LocaleKeys { static const noWinner = 'noWinner'; static const myTeam = 'myTeam'; static const youCanPlayDemo = 'youCanPlayDemo'; + static const group = 'group'; + static const searchGroup = 'searchGroup'; static const connectHmgWifi = 'connectHmgWifi'; static const connectedHmgWifi = 'connectedHmgWifi'; static const itgForms = 'itgForms'; @@ -525,4 +527,26 @@ abstract class LocaleKeys { static const missingDocuments = 'missingDocuments'; static const uploadedDocuments = 'uploadedDocuments'; + static const manage = 'manage'; + static const members = 'members'; + static const areYouSureWantTodelete = 'areYouSureWantTodelete'; + static const groupMembers = "groupMembers"; + static const manageGroup = "manageGroup"; + static const admin = "admin"; + static const addUsers ="addUsers"; + static const editGroups ="editGroups"; + static const groupNameshouldbe ="groupNameshouldbe"; + static const enterGroupName ="enterGroupName"; + static const groupName ="groupName"; + static const enterGroupNamePlease ="enterGroupNamePlease"; + static const audioCall = 'audioCall'; + static const videoCall ='videoCall'; + static const shareScreen ='shareScreen'; + static const searchByUserName ='searchByUserName'; + static const userSearch ='userSearch'; + static const userName ='userName'; + static const userId ='userId'; + static const addAtLeastOneAttachment ='addAtLeastOneAttachment'; + static const pleaseClickButtonToJoinMarathon ='pleaseClickButtonToJoinMarathon'; + static const youCannotJoinTheMarathon ='youCannotJoinTheMarathon'; } diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index 4105def..9189ef6 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -14,6 +14,7 @@ import 'package:fluttertoast/fluttertoast_web.dart'; import 'package:geolocator_web/geolocator_web.dart'; import 'package:image_picker_for_web/image_picker_for_web.dart'; import 'package:just_audio_web/just_audio_web.dart'; +// import 'package:record_web/record_web.dart'; import 'package:shared_preferences_web/shared_preferences_web.dart'; import 'package:url_launcher_web/url_launcher_web.dart'; import 'package:video_player_web/video_player_web.dart'; @@ -30,6 +31,7 @@ void registerPlugins(Registrar registrar) { GeolocatorPlugin.registerWith(registrar); ImagePickerPlugin.registerWith(registrar); JustAudioPlugin.registerWith(registrar); + //RecordPluginWeb.registerWith(registrar); SharedPreferencesPlugin.registerWith(registrar); UrlLauncherPlugin.registerWith(registrar); VideoPlayerPlugin.registerWith(registrar); diff --git a/lib/main.dart b/lib/main.dart index b31ccc3..c066703 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,7 +9,6 @@ import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/codegen_loader.g.dart'; import 'package:mohem_flutter_app/models/post_params_model.dart'; -import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/provider/eit_provider_model.dart'; @@ -20,6 +19,12 @@ import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:sizer/sizer.dart'; + + +// test uat account +// username 199067 +// pass h123456 + late HubConnection chatHubConnection; Logger logger = Logger( // filter: null, // Use the default LogFilter (-> only log in debug mode) @@ -71,9 +76,9 @@ Future main() async { ChangeNotifierProvider( create: (_) => MarathonProvider(), ), - ChangeNotifierProvider( - create: (_) => ChatCallProvider(), - ), + // ChangeNotifierProvider( + // create: (_) => ChatCallProvider(), + // ), ], child: const MyApp(), ), diff --git a/lib/models/chat/create_group_request.dart b/lib/models/chat/create_group_request.dart new file mode 100644 index 0000000..b33297f --- /dev/null +++ b/lib/models/chat/create_group_request.dart @@ -0,0 +1,159 @@ +import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; + +class CreateGroupRequest { + String? groupName; + int? adminUserId; + List? groupUserList; + bool? canAttach; + bool? canAudioC; + bool? canShareS; + bool? canVideoC; + bool? isMeeting; + bool? canArchive; + int? groupId; + CreateGroupRequest( + {this.groupName, + this.adminUserId, + this.groupUserList, + this.canAttach, + this.canAudioC, + this.canShareS, + this.canVideoC, + this.isMeeting, + this.canArchive, + this.groupId + }); + + CreateGroupRequest.fromJson(Map json) { + groupName = json['groupName']; + adminUserId = json['adminUserId']; + if (json['groupUserList'] != null) { + groupUserList = []; + json['groupUserList'].forEach((v) { + groupUserList!.add(new ChatUser.fromJson(v)); + }); + } + canAttach = json['canAttach']; + canAudioC = json['canAudioC']; + canShareS = json['canShareS']; + canVideoC = json['canVideoC']; + isMeeting = json['isMeeting']; + canArchive = json['canArchive']; + groupId = json['groupId']; + } + + Map toJson() { + Map data = new Map(); + data['groupName'] = this.groupName; + data['adminUserId'] = this.adminUserId; + if (this.groupUserList != null) { + data['groupUserList'] = + this.groupUserList!.map((v) => v.toJson()).toList(); + } + data['canAttach'] = this.canAttach; + data['canAudioC'] = this.canAudioC; + data['canShareS'] = this.canShareS; + data['canVideoC'] = this.canVideoC; + data['isMeeting'] = this.isMeeting; + data['canArchive'] = this.canArchive; + data['groupId'] = this.groupId; + return data; + } +} + +class GroupUserList { + int? id; + String? userName; + String? email; + dynamic? phone; + String? title; + int? userStatus; + String? image; + int? unreadMessageCount; + int? userAction; + bool? isPin; + bool? isFav; + bool? isAdmin; + Null? rKey; + int? totalCount; + bool? isHuaweiDevice; + Null? deviceToken; + String? token; + bool? isDomainUser; + bool? isActiveCode; + String? encryptedUserId; + String? encryptedUserName; + + GroupUserList( + {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.rKey, + this.totalCount, + this.isHuaweiDevice, + this.deviceToken, + this.token, + this.isDomainUser, + this.isActiveCode, + this.encryptedUserId, + this.encryptedUserName}); + + GroupUserList.fromJson(Map json) { + id = json['id']; + userName = json['userName']; + email = json['email']; + phone = json['phone']; + title = json['title']; + userStatus = json['userStatus']; + image = json['image']; + unreadMessageCount = json['unreadMessageCount']; + userAction = json['userAction']; + isPin = json['isPin']; + isFav = json['isFav']; + isAdmin = json['isAdmin']; + rKey = json['rKey']; + totalCount = json['totalCount']; + isHuaweiDevice = json['isHuaweiDevice']; + deviceToken = json['deviceToken']; + token = json['token']; + isDomainUser = json['isDomainUser']; + isActiveCode = json['isActiveCode']; + encryptedUserId = json['encryptedUserId']; + encryptedUserName = json['encryptedUserName']; + } + + Map toJson() { + Map data = new Map(); + data['id'] = this.id; + data['userName'] = this.userName; + data['email'] = this.email; + data['phone'] = this.phone; + data['title'] = this.title; + data['userStatus'] = this.userStatus; + data['image'] = this.image; + data['unreadMessageCount'] = this.unreadMessageCount; + data['userAction'] = this.userAction; + data['isPin'] = this.isPin; + data['isFav'] = this.isFav; + data['isAdmin'] = this.isAdmin; + data['rKey'] = this.rKey; + data['totalCount'] = this.totalCount; + data['isHuaweiDevice'] = this.isHuaweiDevice; + data['deviceToken'] = this.deviceToken; + data['token'] = this.token; + data['isDomainUser'] = this.isDomainUser; + data['isActiveCode'] = this.isActiveCode; + data['encryptedUserId'] = this.encryptedUserId; + data['encryptedUserName'] = this.encryptedUserName; + return data; + } +} diff --git a/lib/models/chat/get_group_chat_history.dart b/lib/models/chat/get_group_chat_history.dart new file mode 100644 index 0000000..c8476b1 --- /dev/null +++ b/lib/models/chat/get_group_chat_history.dart @@ -0,0 +1,264 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:just_audio/just_audio.dart'; + +class GetGroupChatHistoryAsync { + int? groupChatHistoryId; + String? contant; + String? contantNo; + int? chatEventId; + dynamic? fileTypeId; + bool? isSeen; + bool? isDelivered; + String? createdDate; + int? chatSource; + int? currentUserId; + String? currentUserName; + int? groupId; + String? groupName; + dynamic? encryptedGroupId; + dynamic? encryptedGroupName; + dynamic? callStatus; + String? conversationId; + List? groupChatHistoryTargetUserList; + FileTypeResponse? fileTypeResponse; + GroupChatReplyResponse? groupChatReplyResponse; + bool? isReplied; + bool? isImageLoaded; + Uint8List? image; + File? voice; + AudioPlayer? voiceController; + GetGroupChatHistoryAsync( + {this.groupChatHistoryId, + this.contant, + this.contantNo, + this.chatEventId, + this.fileTypeId, + this.isSeen, + this.isDelivered, + this.createdDate, + this.chatSource, + this.currentUserId, + this.currentUserName, + this.groupId, + this.groupName, + this.encryptedGroupId, + this.encryptedGroupName, + this.callStatus, + this.conversationId, + this.groupChatHistoryTargetUserList, + this.fileTypeResponse, + this.groupChatReplyResponse, + this.image, + this.isImageLoaded, + this.isReplied, + this.voice, + this.voiceController + }); + + GetGroupChatHistoryAsync.fromJson(Map json) { + groupChatHistoryId = json['groupChatHistoryId']; + contant = json['contant']; + contantNo = json['contantNo']; + chatEventId = json['chatEventId']; + fileTypeId = json['fileTypeId']; + isSeen = json['isSeen']; + isDelivered = json['isDelivered']; + createdDate = json['createdDate']; + chatSource = json['chatSource']; + currentUserId = json['currentUserId']; + currentUserName = json['currentUserName']; + groupId = json['groupId']; + groupName = json['groupName']; + encryptedGroupId = json['encryptedGroupId']; + encryptedGroupName = json['encryptedGroupName']; + callStatus = json['callStatus']; + conversationId = json['conversationId']; + if (json['groupChatHistoryTargetUserList'] != null) { + groupChatHistoryTargetUserList = []; + json['groupChatHistoryTargetUserList'].forEach((v) { + groupChatHistoryTargetUserList! + .add(new GroupChatHistoryTargetUserList.fromJson(v)); + }); + } + fileTypeResponse = json['fileTypeResponse'] != null + ? new FileTypeResponse.fromJson(json['fileTypeResponse']) + : null; + groupChatReplyResponse = json["groupChatReplyResponse"] == null ? null : GroupChatReplyResponse.fromJson(json["groupChatReplyResponse"]); + + isReplied= json['isReplied']; + isImageLoaded= json['isImageLoaded'] ??false; + image= json['image']; + voice= json['voice']; + voiceController = json["fileTypeId"] == 13 ? AudioPlayer() : null; + } + + Map toJson() { + Map data = new Map(); + data['groupChatHistoryId'] = this.groupChatHistoryId; + data['contant'] = this.contant; + data['contantNo'] = this.contantNo; + data['chatEventId'] = this.chatEventId; + data['fileTypeId'] = this.fileTypeId; + data['isSeen'] = this.isSeen; + data['isDelivered'] = this.isDelivered; + data['createdDate'] = this.createdDate; + data['chatSource'] = this.chatSource; + data['currentUserId'] = this.currentUserId; + data['currentUserName'] = this.currentUserName; + data['groupId'] = this.groupId; + data['groupName'] = this.groupName; + data['encryptedGroupId'] = this.encryptedGroupId; + data['encryptedGroupName'] = this.encryptedGroupName; + data['callStatus'] = this.callStatus; + data['conversationId'] = this.conversationId; + if (this.groupChatHistoryTargetUserList != null) { + data['groupChatHistoryTargetUserList'] = + this.groupChatHistoryTargetUserList!.map((v) => v.toJson()).toList(); + } + if (this.fileTypeResponse != null) { + data['fileTypeResponse'] = this.fileTypeResponse!.toJson(); + } + if(this.groupChatReplyResponse !=null) { + data['groupChatReplyResponse'] = this.groupChatReplyResponse; + } + + data['isReplied'] =isReplied; + data['isImageLoaded'] = isImageLoaded ?? false; + data['image'] = image; + data['voice'] = voice; + data["fileTypeId"] == 13 ? AudioPlayer() : null; + return data; + } +} + +class GroupChatHistoryTargetUserList { + int? groupChatHistoryLineId; + bool? isSeen; + bool? isDelivered; + int? targetUserId; + String? targetUserName; + dynamic? userAction; + + GroupChatHistoryTargetUserList( + {this.groupChatHistoryLineId, + this.isSeen, + this.isDelivered, + this.targetUserId, + this.targetUserName, + this.userAction}); + + GroupChatHistoryTargetUserList.fromJson(Map json) { + groupChatHistoryLineId = json['groupChatHistoryLineId']; + isSeen = json['isSeen']; + isDelivered = json['isDelivered']; + targetUserId = json['targetUserId']; + targetUserName = json['targetUserName']; + userAction = json['userAction']; + } + + Map toJson() { + Map data = new Map(); + data['groupChatHistoryLineId'] = this.groupChatHistoryLineId; + data['isSeen'] = this.isSeen; + data['isDelivered'] = this.isDelivered; + data['targetUserId'] = this.targetUserId; + data['targetUserName'] = this.targetUserName; + data['userAction'] = this.userAction; + return data; + } +} + +class FileTypeResponse { + int? fileTypeId; + dynamic? fileTypeName; + dynamic? fileTypeDescription; + dynamic? fileKind; + dynamic? fileName; + + FileTypeResponse( + {this.fileTypeId, + this.fileTypeName, + this.fileTypeDescription, + this.fileKind, + this.fileName}); + + FileTypeResponse.fromJson(Map json) { + fileTypeId = json['fileTypeId']; + fileTypeName = json['fileTypeName']; + fileTypeDescription = json['fileTypeDescription']; + fileKind = json['fileKind']; + fileName = json['fileName']; + } + + Map toJson() { + Map data = new Map(); + data['fileTypeId'] = this.fileTypeId; + data['fileTypeName'] = this.fileTypeName; + data['fileTypeDescription'] = this.fileTypeDescription; + data['fileKind'] = this.fileKind; + data['fileName'] = this.fileName; + return data; + } + +} + + +class GroupChatReplyResponse { + GroupChatReplyResponse( + {this.userChatHistoryId, + this.chatEventId, + this.contant, + this.contantNo, + this.fileTypeId, + this.createdDate, + this.targetUserId, + this.targetUserName, + this.fileTypeResponse, + this.isImageLoaded, + this.image, + this.voice}); + + int? userChatHistoryId; + int? chatEventId; + String? contant; + String? contantNo; + dynamic? fileTypeId; + DateTime? createdDate; + int? targetUserId; + String? targetUserName; + FileTypeResponse? fileTypeResponse; + bool? isImageLoaded; + Uint8List? image; + Uint8List? voice; + + factory GroupChatReplyResponse.fromJson(Map json) => GroupChatReplyResponse( + userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"], + chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], + contant: json["contant"] == null ? null : json["contant"], + contantNo: json["contantNo"] == null ? null : json["contantNo"], + fileTypeId: json["fileTypeId"], + createdDate: json["createdDate"] == null ? null : DateTime.parse(json["createdDate"]), + targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], + targetUserName: json["targetUserName"] == null ? null : json["targetUserName"], + fileTypeResponse: json["fileTypeResponse"] == null ? null : FileTypeResponse.fromJson(json["fileTypeResponse"]), + isImageLoaded: false, + image: null, + voice: null, + ); + + Map toJson() => { + "userChatHistoryId": userChatHistoryId == null ? null : userChatHistoryId, + "chatEventId": chatEventId == null ? null : chatEventId, + "contant": contant == null ? null : contant, + "contantNo": contantNo == null ? null : contantNo, + "fileTypeId": fileTypeId, + "createdDate": createdDate == null ? null : createdDate!.toIso8601String(), + "targetUserId": targetUserId == null ? null : targetUserId, + "targetUserName": targetUserName == null ? null : targetUserName, + "fileTypeResponse": fileTypeResponse == null ? null : fileTypeResponse!.toJson(), + }; +} + diff --git a/lib/models/chat/get_search_user_chat_model.dart b/lib/models/chat/get_search_user_chat_model.dart index e69fd3b..7c638e9 100644 --- a/lib/models/chat/get_search_user_chat_model.dart +++ b/lib/models/chat/get_search_user_chat_model.dart @@ -69,6 +69,7 @@ class ChatUser { this.isImageLoaded, this.isImageLoading, this.userLocalDownlaodedImage, + this.isChecked }); int? id; @@ -89,7 +90,7 @@ class ChatUser { bool? isImageLoaded; bool? isImageLoading; File? userLocalDownlaodedImage; - + bool? isChecked; factory ChatUser.fromRawJson(String str) => ChatUser.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); @@ -112,7 +113,9 @@ class ChatUser { isTyping: false, isImageLoaded: false, isImageLoading: true, - userLocalDownlaodedImage: null); + userLocalDownlaodedImage: null, + isChecked: false + ); Map toJson() => { "id": id == null ? null : id, @@ -129,5 +132,6 @@ class ChatUser { "isAdmin": isAdmin == null ? null : isAdmin, "rKey": rKey, "totalCount": totalCount == null ? null : totalCount, + "isChecked":isChecked }; } diff --git a/lib/models/chat/get_user_groups_by_id.dart b/lib/models/chat/get_user_groups_by_id.dart new file mode 100644 index 0000000..2520c43 --- /dev/null +++ b/lib/models/chat/get_user_groups_by_id.dart @@ -0,0 +1,261 @@ +import 'dart:convert'; + +class GetUserGroups { + List? groupresponse; + Null? errorResponses; + + GetUserGroups({this.groupresponse, this.errorResponses}); + factory GetUserGroups.fromRawJson(String str) => GetUserGroups.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + GetUserGroups.fromJson(Map json) { + if (json['response'] != null) { + groupresponse = []; + json['response'].forEach((v) { + if(v['isDeleted'] == false) + groupresponse!.add(new GroupResponse.fromJson(v)); + }); + } + errorResponses = json['errorResponses']; + } + + Map toJson() { + Map data = new Map(); + if (this.groupresponse != null) { + data['response'] = this.groupresponse!.map((v) => v.toJson()).toList(); + } + data['errorResponses'] = this.errorResponses; + return data; + } +} + +class GroupResponse { + int? groupId; + String? groupName; + Null? groupIcon; + bool? isDeleted; + bool? isAdmin; + bool? canVideoC; + bool? canAudioC; + bool? canShareS; + bool? canAttach; + bool? canArchive; + bool? isMeeting; + Null? meetingTime; + Null? extUserLink; + int? callStatus; + int? groupUnreadMessageCount; + AdminUser? adminUser; + List? groupUserList; + + GroupResponse( + {this.groupId, + this.groupName, + this.groupIcon, + this.isDeleted, + this.isAdmin, + this.canVideoC, + this.canAudioC, + this.canShareS, + this.canAttach, + this.canArchive, + this.isMeeting, + this.meetingTime, + this.extUserLink, + this.callStatus, + this.groupUnreadMessageCount, + this.adminUser, + this.groupUserList}); + + GroupResponse.fromJson(Map json) { + groupId = json['groupId']; + groupName = json['groupName']; + groupIcon = json['groupIcon']; + isDeleted = json['isDeleted']; + isAdmin = json['isAdmin']; + canVideoC = json['canVideoC']; + canAudioC = json['canAudioC']; + canShareS = json['canShareS']; + canAttach = json['canAttach']; + canArchive = json['canArchive']; + isMeeting = json['isMeeting']; + meetingTime = json['meetingTime']; + extUserLink = json['extUserLink']; + callStatus = json['callStatus']; + groupUnreadMessageCount = json['groupUnreadMessageCount']; + adminUser = json['adminUser'] != null + ? new AdminUser.fromJson(json['adminUser']) + : null; + if (json['groupUserList'] != null) { + groupUserList = []; + json['groupUserList'].forEach((v) { + groupUserList!.add(new GroupUserList.fromJson(v)); + }); + } + } + + Map toJson() { + Map data = new Map(); + data['groupId'] = this.groupId; + data['groupName'] = this.groupName; + data['groupIcon'] = this.groupIcon; + data['isDeleted'] = this.isDeleted; + data['isAdmin'] = this.isAdmin; + data['canVideoC'] = this.canVideoC; + data['canAudioC'] = this.canAudioC; + data['canShareS'] = this.canShareS; + data['canAttach'] = this.canAttach; + data['canArchive'] = this.canArchive; + data['isMeeting'] = this.isMeeting; + data['meetingTime'] = this.meetingTime; + data['extUserLink'] = this.extUserLink; + data['callStatus'] = this.callStatus; + data['groupUnreadMessageCount'] = this.groupUnreadMessageCount; + if (this.adminUser != null) { + data['adminUser'] = this.adminUser!.toJson(); + } + if (this.groupUserList != null) { + data['groupUserList'] = + this.groupUserList!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class AdminUser { + int? id; + String? userName; + String? email; + Null? phone; + String? title; + int? userStatus; + Null? image; + int? unreadMessageCount; + Null? userAction; + bool? isPin; + bool? isFav; + bool? isAdmin; + Null? rKey; + int? totalCount; + + AdminUser( + {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.rKey, + this.totalCount}); + + AdminUser.fromJson(Map json) { + id = json['id']; + userName = json['userName']; + email = json['email']; + phone = json['phone']; + title = json['title']; + userStatus = json['userStatus']; + image = json['image']; + unreadMessageCount = json['unreadMessageCount']; + userAction = json['userAction']; + isPin = json['isPin']; + isFav = json['isFav']; + isAdmin = json['isAdmin']; + rKey = json['rKey']; + totalCount = json['totalCount']; + } + + Map toJson() { + Map data = new Map(); + data['id'] = this.id; + data['userName'] = this.userName; + data['email'] = this.email; + data['phone'] = this.phone; + data['title'] = this.title; + data['userStatus'] = this.userStatus; + data['image'] = this.image; + data['unreadMessageCount'] = this.unreadMessageCount; + data['userAction'] = this.userAction; + data['isPin'] = this.isPin; + data['isFav'] = this.isFav; + data['isAdmin'] = this.isAdmin; + data['rKey'] = this.rKey; + data['totalCount'] = this.totalCount; + return data; + } +} + +class GroupUserList { + int? id; + String? userName; + String? email; + Null? phone; + String? title; + int? userStatus; + Null? image; + int? unreadMessageCount; + int? userAction; + bool? isPin; + bool? isFav; + bool? isAdmin; + Null? rKey; + int? totalCount; + + GroupUserList( + {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.rKey, + this.totalCount}); + + GroupUserList.fromJson(Map json) { + id = json['id']; + userName = json['userName']; + email = json['email']; + phone = json['phone']; + title = json['title']; + userStatus = json['userStatus']; + image = json['image']; + unreadMessageCount = json['unreadMessageCount']; + userAction = json['userAction']; + isPin = json['isPin']; + isFav = json['isFav']; + isAdmin = json['isAdmin']; + rKey = json['rKey']; + totalCount = json['totalCount']; + } + + Map toJson() { + Map data = new Map(); + data['id'] = this.id; + data['userName'] = this.userName; + data['email'] = this.email; + data['phone'] = this.phone; + data['title'] = this.title; + data['userStatus'] = this.userStatus; + data['image'] = this.image; + data['unreadMessageCount'] = this.unreadMessageCount; + data['userAction'] = this.userAction; + data['isPin'] = this.isPin; + data['isFav'] = this.isFav; + data['isAdmin'] = this.isAdmin; + data['rKey'] = this.rKey; + data['totalCount'] = this.totalCount; + return data; + } +} diff --git a/lib/models/chat/target_users.dart b/lib/models/chat/target_users.dart new file mode 100644 index 0000000..d399a38 --- /dev/null +++ b/lib/models/chat/target_users.dart @@ -0,0 +1,32 @@ +class TargetUsers { + bool? isSeen; + bool? isDelivered; + int? targetUserId; + int? userAction; + int? userStatus; + + TargetUsers( + {this.isSeen, + this.isDelivered, + this.targetUserId, + this.userAction, + this.userStatus}); + + TargetUsers.fromJson(Map json) { + isSeen = json['isSeen']; + isDelivered = json['isDelivered']; + targetUserId = json['targetUserId']; + userAction = json['userAction']; + userStatus = json['userStatus']; + } + + Map toJson() { + Map data = new Map(); + data['isSeen'] = this.isSeen; + data['isDelivered'] = this.isDelivered; + data['targetUserId'] = this.targetUserId; + data['userAction'] = this.userAction; + data['userStatus'] = this.userStatus; + return data; + } +} diff --git a/lib/models/itg/advertisement.dart b/lib/models/itg/advertisement.dart index 96f4037..ebcf704 100644 --- a/lib/models/itg/advertisement.dart +++ b/lib/models/itg/advertisement.dart @@ -1,108 +1,156 @@ class Advertisement { + int? advertisementId; + String? advertisementTitle; + int? durationInSeconds; + bool? showDelete; + dynamic acknowledgment; + late bool isOptional; + List? viewAttachFileColl; + int? skipButtonId; + List? actionButtonsColl; + bool? isActive; + num? pageSize; + num? pageNo; + num? languageId; + Advertisement({ this.advertisementId, this.advertisementTitle, this.durationInSeconds, this.showDelete, this.acknowledgment, + required this.isOptional, + // this.skipBtnTextEn, + // this.skipBtnTextAr, this.viewAttachFileColl, + this.skipButtonId, + this.actionButtonsColl, this.isActive, this.pageSize, this.pageNo, this.languageId, - this.isOptional, - this.skipButtonTextEn, - this.skipButtonTextAr, }); - final int? advertisementId; - final String? advertisementTitle; - final int? durationInSeconds; - final bool? showDelete; - final dynamic acknowledgment; - final List? viewAttachFileColl; - final bool? isActive; - final dynamic pageSize; - final dynamic pageNo; - final dynamic languageId; - final bool? isOptional; - final String? skipButtonTextEn; - final String? skipButtonTextAr; - - factory Advertisement.fromJson(Map json) => Advertisement( - advertisementId: json["advertisementId"] == null ? null : json["advertisementId"], - advertisementTitle: json["advertisementTitle"] == null ? null : json["advertisementTitle"], - durationInSeconds: json["durationInSeconds"] == null ? null : json["durationInSeconds"], - showDelete: json["showDelete"] == null ? null : json["showDelete"], - acknowledgment: json["acknowledgment"], - viewAttachFileColl: json["viewAttachFileColl"] == null ? null : List.from(json["viewAttachFileColl"].map((x) => ViewAttachFileColl.fromJson(x))), - isActive: json["isActive"] == null ? null : json["isActive"], - pageSize: json["pageSize"], - pageNo: json["pageNo"], - languageId: json["languageId"], - isOptional: json["isOptional"] == null ? null : json["isOptional"], - skipButtonTextEn: json["skipBtnTextEn"] == null ? null : json["skipBtnTextEn"], - skipButtonTextAr: json["skipBtnTextAr"] == null ? null : json["skipBtnTextAr"], - ); + Advertisement.fromJson(Map json) { + advertisementId = json['advertisementId']; + advertisementTitle = json['advertisementTitle']; + durationInSeconds = json['durationInSeconds']; + showDelete = json['showDelete']; + acknowledgment = json['acknowledgment']; + isOptional = json['isOptional']; + // skipBtnTextEn = json['skipBtnTextEn']; + // skipBtnTextAr = json['skipBtnTextAr']; + if (json['viewAttachFileColl'] != null) { + viewAttachFileColl = []; + json['viewAttachFileColl'].forEach((v) { + viewAttachFileColl!.add(ViewAttachFileColl.fromJson(v)); + }); + } + skipButtonId = json['skipButtonId']; + if (json['actionButtonsColl'] != null) { + actionButtonsColl = []; + json['actionButtonsColl'].forEach((v) { + actionButtonsColl!.add(ActionButtonsColl.fromJson(v)); + }); + } + isActive = json['isActive']; + pageSize = json['pageSize']; + pageNo = json['pageNo']; + languageId = json['languageId']; + } - Map toJson() => { - "advertisementId": advertisementId == null ? null : advertisementId, - "advertisementTitle": advertisementTitle == null ? null : advertisementTitle, - "durationInSeconds": durationInSeconds == null ? null : durationInSeconds, - "showDelete": showDelete == null ? null : showDelete, - "acknowledgment": acknowledgment, - "viewAttachFileColl": viewAttachFileColl == null ? null : List.from(viewAttachFileColl!.map((x) => x.toJson())), - "isActive": isActive == null ? null : isActive, - "pageSize": pageSize, - "pageNo": pageNo, - "languageId": languageId, - }; + Map toJson() { + Map data = Map(); + data['advertisementId'] = this.advertisementId; + data['advertisementTitle'] = this.advertisementTitle; + data['durationInSeconds'] = this.durationInSeconds; + data['showDelete'] = this.showDelete; + data['acknowledgment'] = this.acknowledgment; + data['isOptional'] = this.isOptional; + // data['skipBtnTextEn'] = this.skipBtnTextEn; + // data['skipBtnTextAr'] = this.skipBtnTextAr; + if (this.viewAttachFileColl != null) { + data['viewAttachFileColl'] = this.viewAttachFileColl!.map((v) => v.toJson()).toList(); + } + data['skipButtonId'] = this.skipButtonId; + if (this.actionButtonsColl != null) { + data['actionButtonsColl'] = this.actionButtonsColl!.map((v) => v.toJson()).toList(); + } + data['isActive'] = this.isActive; + data['pageSize'] = this.pageSize; + data['pageNo'] = this.pageNo; + data['languageId'] = this.languageId; + return data; + } } class ViewAttachFileColl { - ViewAttachFileColl({ - this.attachmentId, - this.fileName, - this.contentType, - this.attachFileStream, - this.base64String, - this.isActive, - this.referenceItemId, - this.content, - this.filePath, - }); + dynamic attachmentId; + String? fileName; + String? contentType; + dynamic attachFileStream; + String? base64String; + dynamic isActive; + dynamic referenceItemId; + dynamic content; + dynamic filePath; + + ViewAttachFileColl({this.attachmentId, this.fileName, this.contentType, this.attachFileStream, this.base64String, this.isActive, this.referenceItemId, this.content, this.filePath}); + + ViewAttachFileColl.fromJson(Map json) { + attachmentId = json['attachmentId']; + fileName = json['fileName']; + contentType = json['contentType']; + attachFileStream = json['attachFileStream']; + base64String = json['base64String']; + isActive = json['isActive']; + referenceItemId = json['referenceItemId']; + content = json['content']; + filePath = json['filePath']; + } + + Map toJson() { + Map data = new Map(); + data['attachmentId'] = this.attachmentId; + data['fileName'] = this.fileName; + data['contentType'] = this.contentType; + data['attachFileStream'] = this.attachFileStream; + data['base64String'] = this.base64String; + data['isActive'] = this.isActive; + data['referenceItemId'] = this.referenceItemId; + data['content'] = this.content; + data['filePath'] = this.filePath; + return data; + } +} + +class ActionButtonsColl { + late int actionButtonId; + late String btnTextEn; + late String btnTextAr; + late String actionValue; + late dynamic iconOrImage; + late int orderNo; - final dynamic attachmentId; - final String? fileName; - final String? contentType; - final dynamic attachFileStream; - final String? base64String; - final dynamic isActive; - final dynamic referenceItemId; - final dynamic content; - final dynamic filePath; + ActionButtonsColl({required this.actionButtonId, required this.btnTextEn, required this.btnTextAr, required this.actionValue, required this.iconOrImage, required this.orderNo}); - factory ViewAttachFileColl.fromJson(Map json) => ViewAttachFileColl( - attachmentId: json["attachmentId"], - fileName: json["fileName"] == null ? null : json["fileName"], - contentType: json["contentType"] == null ? null : json["contentType"], - attachFileStream: json["attachFileStream"], - base64String: json["base64String"] == null ? null : json["base64String"], - isActive: json["isActive"], - referenceItemId: json["referenceItemId"], - content: json["content"], - filePath: json["filePath"], - ); + ActionButtonsColl.fromJson(Map json) { + actionButtonId = json['actionButtonId']; + btnTextEn = json['btnTextEn']; + btnTextAr = json['btnTextAr']; + actionValue = json['actionValue']; + iconOrImage = json['iconOrImage']; + orderNo = json['orderNo']; + } - Map toJson() => { - "attachmentId": attachmentId, - "fileName": fileName == null ? null : fileName, - "contentType": contentType == null ? null : contentType, - "attachFileStream": attachFileStream, - "base64String": base64String == null ? null : base64String, - "isActive": isActive, - "referenceItemId": referenceItemId, - "content": content, - "filePath": filePath, - }; + Map toJson() { + Map data = new Map(); + data['actionButtonId'] = this.actionButtonId; + data['btnTextEn'] = this.btnTextEn; + data['btnTextAr'] = this.btnTextAr; + data['actionValue'] = this.actionValue; + data['iconOrImage'] = this.iconOrImage; + data['orderNo'] = this.orderNo; + return data; + } } diff --git a/lib/models/itg/survey_model.dart b/lib/models/itg/survey_model.dart index 7cdbbdd..f9ac415 100644 --- a/lib/models/itg/survey_model.dart +++ b/lib/models/itg/survey_model.dart @@ -5,9 +5,9 @@ class SurveyModel { String? description; List? questions; bool? isActive; - Null? pageSize; - Null? pageNo; - Null? languageId; + dynamic pageSize; + dynamic pageNo; + dynamic languageId; SurveyModel({this.surveyId, this.referenceNo, this.title, this.description, this.questions, this.isActive, this.pageSize, this.pageNo, this.languageId}); @@ -51,13 +51,13 @@ class Questions { bool? isRequired; String? type; int? sequenceNo; - Null? surveyId; + dynamic surveyId; List? options; - Null? rspPercentage; - Null? isActive; - Null? pageSize; - Null? pageNo; - Null? languageId; + dynamic rspPercentage; + dynamic isActive; + dynamic pageSize; + dynamic pageNo; + dynamic languageId; Questions({this.questionId, this.title, this.isRequired, this.type, this.sequenceNo, this.surveyId, this.options, this.rspPercentage, this.isActive, this.pageSize, this.pageNo, this.languageId}); @@ -107,12 +107,12 @@ class Options { bool? isCommentsRequired; int? sequenceNo; int? questionId; - Null? rspPercentage; - Null? count; - Null? isActive; - Null? pageSize; - Null? pageNo; - Null? languageId; + dynamic rspPercentage; + dynamic count; + dynamic isActive; + dynamic pageSize; + dynamic pageNo; + dynamic languageId; Options({this.optionId, this.title, this.isCommentsRequired, this.sequenceNo, this.questionId, this.rspPercentage, this.count, this.isActive, this.pageSize, this.pageNo, this.languageId}); diff --git a/lib/models/itg_forms_models/itg_request_model.dart b/lib/models/itg_forms_models/itg_request_model.dart index ba10305..87d8280 100644 --- a/lib/models/itg_forms_models/itg_request_model.dart +++ b/lib/models/itg_forms_models/itg_request_model.dart @@ -6,7 +6,7 @@ class ITGRequest { List? allowedActions; List? attachments; List? fieldGoups; - Null? grantFields; + dynamic grantFields; List? wFHistory; ITGRequest({this.allowedActions, this.attachments, this.fieldGoups, this.grantFields, this.wFHistory}); diff --git a/lib/models/itg_forms_models/request_detail_model.dart b/lib/models/itg_forms_models/request_detail_model.dart index 1193423..e6d2ca8 100644 --- a/lib/models/itg_forms_models/request_detail_model.dart +++ b/lib/models/itg_forms_models/request_detail_model.dart @@ -1,6 +1,6 @@ class RequestDetails { - int? iD; - int? itemID; + dynamic iD; + dynamic itemID; String? listID; String? listName; String? modifiedDate; diff --git a/lib/models/my_documents/employee_documents_list_model.dart b/lib/models/my_documents/employee_documents_list_model.dart index 97ef785..b91bc3d 100644 --- a/lib/models/my_documents/employee_documents_list_model.dart +++ b/lib/models/my_documents/employee_documents_list_model.dart @@ -2,28 +2,35 @@ class EmployeeDocumentsList { String? dOCUMENTREQUIREDSTATUS; String? dOCUMENTSTATUS; String? dOCUMENTTYPE; + String? dOCUMENTTYPENAME; + String? eNTITLEDTOAPPLYFLAG; String? fUNCTIONNAME; - EmployeeDocumentsList({ - this.dOCUMENTREQUIREDSTATUS, - this.dOCUMENTSTATUS, - this.dOCUMENTTYPE, - this.fUNCTIONNAME, - }); + EmployeeDocumentsList( + {this.dOCUMENTREQUIREDSTATUS, + this.dOCUMENTSTATUS, + this.dOCUMENTTYPE, + this.dOCUMENTTYPENAME, + this.eNTITLEDTOAPPLYFLAG, + this.fUNCTIONNAME}); EmployeeDocumentsList.fromJson(Map json) { dOCUMENTREQUIREDSTATUS = json['DOCUMENT_REQUIRED_STATUS']; dOCUMENTSTATUS = json['DOCUMENT_STATUS']; dOCUMENTTYPE = json['DOCUMENT_TYPE']; + dOCUMENTTYPENAME = json['DOCUMENT_TYPE_NAME']; + eNTITLEDTOAPPLYFLAG = json['ENTITLED_TO_APPLY_FLAG']; fUNCTIONNAME = json['FUNCTION_NAME']; } Map toJson() { - Map data = Map(); - data['DOCUMENT_REQUIRED_STATUS'] = dOCUMENTREQUIREDSTATUS; - data['DOCUMENT_STATUS'] = dOCUMENTSTATUS; - data['DOCUMENT_TYPE'] = dOCUMENTTYPE; - data['FUNCTION_NAME'] = fUNCTIONNAME; + Map data = new Map(); + data['DOCUMENT_REQUIRED_STATUS'] = this.dOCUMENTREQUIREDSTATUS; + data['DOCUMENT_STATUS'] = this.dOCUMENTSTATUS; + data['DOCUMENT_TYPE'] = this.dOCUMENTTYPE; + data['DOCUMENT_TYPE_NAME'] = this.dOCUMENTTYPENAME; + data['ENTITLED_TO_APPLY_FLAG'] = this.eNTITLEDTOAPPLYFLAG; + data['FUNCTION_NAME'] = this.fUNCTIONNAME; return data; } -} +} \ No newline at end of file diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 7d2630c..908e8dd 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -19,10 +19,20 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart'; +import 'package:mohem_flutter_app/models/chat/create_group_request.dart' + as createGroup; +import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart' + as groupchathistory; 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 userLoginToken; -import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' + as groups; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' + as userLoginToken; +import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' + as fav; +import 'package:mohem_flutter_app/models/chat/target_users.dart'; import 'package:mohem_flutter_app/models/my_team/get_employee_subordinates_list.dart'; import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; @@ -42,6 +52,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { TextEditingController message = TextEditingController(); TextEditingController search = TextEditingController(); + TextEditingController searchGroup = TextEditingController(); + List userChatHistory = [], repliedMsg = []; List? pChatHistory, searchedChats; String chatCID = ''; @@ -54,7 +66,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; int? cTypingUserId = 0; - bool isTextMsg = false, isReplyMsg = false, isAttachmentMsg = false, isVoiceMsg = false; + bool isTextMsg = false, + isReplyMsg = false, + isAttachmentMsg = false, + isVoiceMsg = false; // Audio Recoding Work Timer? _timer; @@ -69,7 +84,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { late PlayerController playerController; List getEmployeeSubordinatesList = []; List teamMembersList = []; - + groups.GetUserGroups userGroups = groups.GetUserGroups(); Material.TextDirection textDirection = Material.TextDirection.ltr; bool isRTL = false; String msgText = ""; @@ -77,10 +92,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Chat Home Page Counter int chatUConvCounter = 0; + late List groupChatHistory, groupChatReplyData; + /// Search Provider List? chatUsersList = []; int pageNo = 1; + bool disbaleChatForThisUser = false; + List? uGroups = [], searchGroups = []; bool disableChatForThisUser = false; bool isUserOnline = false; bool isCall = false; @@ -133,26 +152,43 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion); ccProvider.initCallListeners(context: context); + + //group On message + + chatHubConnection.on("OnDeliveredGroupChatHistoryAsync", onGroupMsgReceived); } Future getHubConnection() async { HubConnection hub; - HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); + HttpConnectionOptions httpOp = + HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hub = HubConnectionBuilder() - .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) - .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); + .withUrl( + ApiConsts.chatHubConnectionUrl + + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", + options: httpOp) + .withAutomaticReconnect( + retryDelays: [2000, 5000, 10000, 20000]).build(); return hub; } void registerEvents() { chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus); // chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); + chatHubConnection.on("OnSubmitChatAsync", OnSubmitChatAsync); chatHubConnection.on("OnUserTypingAsync", onUserTyping); chatHubConnection.on("OnUserCountAsync", userCountAsync); // chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); - chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + chatHubConnection.on( + "OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + chatHubConnection.on( + "OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + chatHubConnection.on( + "OnGetGroupUserStatusAsync", getGroupUserStatus); + + // + // {"type":1,"target":"","arguments":[[{"id":217869,"userName":"Sultan.Khan","email":"Sultan.Khan@cloudsolutions.com.sa","phone":null,"title":"Sultan.Khan","userStatus":1,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":false,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null},{"id":15153,"userName":"Tamer.Fanasheh","email":"Tamer.F@cloudsolutions.com.sa","phone":null,"title":"Tamer Fanasheh","userStatus":2,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":true,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null}]]} if (kDebugMode) { logger.i("All listeners registered"); @@ -162,9 +198,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getUserRecentChats() async { ChatUserModel recentChat = await ChatApiClient().getRecentChats(); ChatUserModel favUList = await ChatApiClient().getFavUsers(); + // userGroups = await ChatApiClient().getGroupsByUserId(); if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; - favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + favUsersList.sort((ChatUser a, ChatUser b) => + a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); for (dynamic user in recentChat.response!) { for (dynamic favUser in favUList.response!) { if (user.id == favUser.id) { @@ -174,10 +212,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } pChatHistory = recentChat.response ?? []; - pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + uGroups = userGroups.groupresponse ?? []; + pChatHistory!.sort((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())); + await invokeUserChatHistoryNotDeliveredAsync( + userId: int.parse(AppState().chatDetails!.response!.id.toString())); sort(); notifyListeners(); if (searchedChats!.isNotEmpty || favUsersList.isNotEmpty) { @@ -186,27 +227,38 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future invokeUserChatHistoryNotDeliveredAsync({required int userId}) async { - await chatHubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); + await chatHubConnection + .invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); return ""; } - void getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { + void getSingleUserChatHistory( + {required int senderUID, + required int receiverUID, + required bool loadMore, + bool isNewChat = false}) async { isLoading = true; if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; isChatScreenActive = true; receiverID = receiverUID; - Response response = await ChatApiClient().getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); + Response response = await ChatApiClient().getSingleUserChatHistory( + senderUID: senderUID, + receiverUID: receiverUID, + loadMore: loadMore, + paginationVal: paginationVal); if (response.statusCode == 204) { if (isNewChat) { userChatHistory = []; } else if (loadMore) {} } else { if (loadMore) { - List temp = getSingleUserChatModel(response.body).reversed.toList(); + List temp = + getSingleUserChatModel(response.body).reversed.toList(); userChatHistory.addAll(temp); } else { - userChatHistory = getSingleUserChatModel(response.body).reversed.toList(); + userChatHistory = + getSingleUserChatModel(response.body).reversed.toList(); } } isLoading = false; @@ -233,7 +285,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { dynamic data = [ { "userChatHistoryId": element.userChatHistoryId, - "TargetUserId": element.currentUserId == receiverID ? element.currentUserId : element.targetUserId, + "TargetUserId": element.currentUserId == receiverID + ? element.currentUserId + : element.targetUserId, "isDelivered": true, "isSeen": true, } @@ -255,7 +309,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateUserChatHistoryStatusAsync(List data) { try { - chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + chatHubConnection + .invoke("UpdateUserChatHistoryStatusAsync", args: [data]); } catch (e) { throw e; } @@ -263,13 +318,21 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateUserChatHistoryOnMsg(List data) { try { - chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + chatHubConnection + .invoke("UpdateUserChatHistoryStatusAsync", args: [data]); } catch (e) { throw e; } } - List getSingleUserChatModel(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); + List getSingleUserChatModel(String str) => + List.from( + json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); + + List getGroupChatHistoryAsync(String str) => + List.from( + json.decode(str).map((x) => groupchathistory.GetGroupChatHistoryAsync.fromJson(x))); + Future uploadAttachments(String userId, File file) async { dynamic result; @@ -299,6 +362,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } + void getGroupUserStatus(List? args){ + //note: need to implement this function... + print(args); + } + void onChatSeen(List? args) { dynamic items = args!.toList(); // for (var user in searchedChats!) { @@ -325,7 +393,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateChatHistoryWindow(List? args) { dynamic items = args!.toList(); if (kDebugMode) { - logger.i("---------------------------------Update Chat History Windows Async -------------------------------------"); + logger.i( + "---------------------------------Update Chat History Windows Async -------------------------------------"); } logger.d(items); // for (var user in searchedChats!) { @@ -394,14 +463,27 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserId = temp.first.targetUserId; data.first.currentUserName = temp.first.targetUserName; data.first.currentUserEmail = temp.first.targetUserEmail; - if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) { - data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); + + if (data.first.fileTypeId == 12 || + data.first.fileTypeId == 4 || + data.first.fileTypeId == 3) { + data.first.image = await ChatApiClient().downloadURL( + fileName: data.first.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg"); } if (data.first.userChatReplyResponse != null) { if (data.first.fileTypeResponse != null) { - if (data.first.userChatReplyResponse!.fileTypeId == 12 || data.first.userChatReplyResponse!.fileTypeId == 4 || data.first.userChatReplyResponse!.fileTypeId == 3) { - data.first.userChatReplyResponse!.image = - await ChatApiClient().downloadURL(fileName: data.first.userChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); + if (data.first.userChatReplyResponse!.fileTypeId == 12 || + data.first.userChatReplyResponse!.fileTypeId == 4 || + data.first.userChatReplyResponse!.fileTypeId == 3) { + data.first.userChatReplyResponse!.image = await ChatApiClient() + .downloadURL( + fileName: data.first.userChatReplyResponse!.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg"); data.first.userChatReplyResponse!.isImageLoaded = true; } } @@ -409,11 +491,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (searchedChats != null) { - dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId); + dynamic contain = searchedChats! + .where((ChatUser element) => element.id == data.first.currentUserId); if (contain.isEmpty) { List emails = []; - emails.add(await EmailImageEncryption().encrypt(val: data.first.currentUserEmail!)); - List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); + emails.add(await EmailImageEncryption() + .encrypt(val: data.first.currentUserEmail!)); + List chatImages = + await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( id: data.first.currentUserId, @@ -425,7 +510,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoaded: true, userStatus: 1, isTyping: false, - userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, data.first.currentUserId.toString()), + userLocalDownlaodedImage: await downloadImageLocal( + chatImages.first.profilePicture, + data.first.currentUserId.toString()), ), ); } @@ -452,7 +539,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "userChatHistoryId": data.first.userChatHistoryId, "TargetUserId": temp.first.targetUserId, "isDelivered": true, - "isSeen": isChatScreenActive && data.first.currentUserId == receiverID ? true : false + "isSeen": isChatScreenActive && data.first.currentUserId == receiverID + ? true + : false } ]; updateUserChatHistoryOnMsg(list); @@ -460,6 +549,107 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } + Future onGroupMsgReceived(List? parameters) async { + List data = [], temp = []; + + + for (dynamic msg in parameters!) { + // groupChatHistory.add(groupchathistory.GetGroupChatHistoryAsync.fromJson(msg)); + data.add(groupchathistory.GetGroupChatHistoryAsync.fromJson(msg)); + temp =data; + // data.first.currentUserId = temp.first.currentUserId; + // data.first.currentUserName = temp.first.currentUserName; + // + // data.first.currentUserId = temp.first.currentUserId; + // data.first.currentUserName = temp.first.currentUserName; + + + if (data.first.fileTypeId == 12 || + data.first.fileTypeId == 4 || + data.first.fileTypeId == 3) { + data.first.image = await ChatApiClient().downloadURL( + fileName: data.first.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg"); + } + if (data.first.groupChatReplyResponse != null) { + if (data.first.fileTypeResponse != null) { + if (data.first.groupChatReplyResponse!.fileTypeId == 12 || + data.first.groupChatReplyResponse!.fileTypeId == 4 || + data.first.groupChatReplyResponse!.fileTypeId == 3) { + data.first.groupChatReplyResponse!.image = await ChatApiClient() + .downloadURL( + fileName: data.first.groupChatReplyResponse!.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg"); + data.first.groupChatReplyResponse!.isImageLoaded = true; + } + } + } + } + + // if (searchedChats != null) { + // dynamic contain = searchedChats! + // .where((ChatUser element) => element.id == data.first.currentUserId); + // if (contain.isEmpty) { + // List emails = []; + // emails.add(await EmailImageEncryption() + // .encrypt(val: data.first.currentUserEmail!)); + // List chatImages = + // await ChatApiClient().getUsersImages(encryptedEmails: emails); + // searchedChats!.add( + // ChatUser( + // id: data.first.currentUserId, + // userName: data.first.currentUserName, + // email: data.first.currentUserEmail, + // unreadMessageCount: 0, + // isImageLoading: false, + // image: chatImages!.first.profilePicture ?? "", + // isImageLoaded: true, + // userStatus: 1, + // isTyping: false, + // userLocalDownlaodedImage: await downloadImageLocal( + // chatImages.first.profilePicture, + // data.first.currentUserId.toString()), + // ), + // ); + // } + // } + groupChatHistory.insert(0, data.first); + setMsgTune(); + // if (isChatScreenActive && data.first.currentUserId == receiverID) { + + // } else { + // if (searchedChats != null) { + // for (ChatUser user in searchedChats!) { + // if (user.id == data.first.currentUserId) { + // int tempCount = user.unreadMessageCount ?? 0; + // user.unreadMessageCount = tempCount + 1; + // } + // } + sort(); + //} + //} + // + // List list = [ + // { + // "userChatHistoryId": data.first.groupId, + // "TargetUserId": temp.first.currentUserId, + // "isDelivered": true, + // "isSeen": isChatScreenActive && data.first.currentUserId == receiverID + // ? true + // : false + // } + // ]; + // updateUserChatHistoryOnMsg(list); + // invokeChatCounter(userId: AppState().chatDetails!.response!.id!); + notifyListeners(); + } + + + void OnSubmitChatAsync(List? parameters) { List data = [], temp = []; for (dynamic msg in parameters!) { @@ -474,6 +664,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (isChatScreenActive && data.first.currentUserId == receiverID) { int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == 0); + + logger.d(index); userChatHistory[index] = data.first; } @@ -482,7 +674,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void sort() { searchedChats!.sort( - (ChatUser a, ChatUser b) => b.unreadMessageCount!.compareTo(a.unreadMessageCount!), + (ChatUser a, ChatUser b) => + b.unreadMessageCount!.compareTo(a.unreadMessageCount!), ); } @@ -612,14 +805,22 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { targetUserName: targetUserName, isReplied: false, fileTypeId: fileTypeId, - userChatReplyResponse: isReply ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) : null, + userChatReplyResponse: isReply + ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) + : null, fileTypeResponse: isAttachment ? FileTypeResponse( fileTypeId: fileTypeId, - fileTypeName: isVoiceMsg ? getFileExtension(voiceFile!.path).toString() : getFileExtension(selectedFile.path).toString(), + fileTypeName: isVoiceMsg + ? getFileExtension(voiceFile!.path).toString() + : getFileExtension(selectedFile.path).toString(), fileKind: "file", fileName: isVoiceMsg ? msg : selectedFile.path.split("/").last, - fileTypeDescription: isVoiceMsg ? getFileTypeDescription(getFileExtension(voiceFile!.path).toString()) : getFileTypeDescription(getFileExtension(selectedFile.path).toString()), + fileTypeDescription: isVoiceMsg + ? getFileTypeDescription( + getFileExtension(voiceFile!.path).toString()) + : getFileTypeDescription( + getFileExtension(selectedFile.path).toString()), ) : null, image: image, @@ -640,10 +841,298 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String chatData = '{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"$chatCID"}'; - await chatHubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); + + await chatHubConnection + .invoke("AddChatUserAsync", args: [json.decode(chatData)]); } - void sendChatMessage(BuildContext context, {required int targetUserId, required int userStatus, required String userEmail, required String targetUserName}) async { + //groupChatMessage + + Future sendGroupChatToServer( + {required int chatEventId, + required fileTypeId, + required int targetGroupId, + required String targetUserName, + required chatReplyId, + required bool isAttachment, + required bool isReply, + Uint8List? image, + required bool isImageLoaded, + String? userEmail, + int? userStatus, + File? voiceFile, + required bool isVoiceAttached, + required List userList + }) async { + Uuid uuid = const Uuid(); + String contentNo = uuid.v4(); + String msg; + if (isVoiceAttached) { + msg = voiceFile!.path.split("/").last; + } else { + msg = message.text; + logger.w(msg); + } + groupchathistory.GetGroupChatHistoryAsync data = + groupchathistory.GetGroupChatHistoryAsync( + //userChatHistoryId: 0, + chatEventId: chatEventId, + chatSource: 1, + contant: msg, + contantNo: contentNo, + conversationId: chatCID, + createdDate: DateTime.now().toString(), + currentUserId: AppState().chatDetails!.response!.id, + currentUserName: AppState().chatDetails!.response!.userName, + groupId: targetGroupId, + groupName: targetUserName, + isReplied: false, + fileTypeId: fileTypeId, + fileTypeResponse: isAttachment + ? groupchathistory.FileTypeResponse( + fileTypeId: fileTypeId, + fileTypeName: isVoiceMsg ? getFileExtension(voiceFile!.path).toString() : getFileExtension(selectedFile.path).toString(), + fileKind: "file", + fileName: isVoiceMsg ? msg : selectedFile.path.split("/").last, + fileTypeDescription: isVoiceMsg ? getFileTypeDescription(getFileExtension(voiceFile!.path).toString()) : getFileTypeDescription(getFileExtension(selectedFile.path).toString())) : null, + image: image, + isImageLoaded: isImageLoaded, + voice: isVoiceMsg ? voiceFile! : null, + voiceController: isVoiceMsg ? AudioPlayer() : null); + if (kDebugMode) { + logger.i("model data: " + jsonEncode(data)); + } + groupChatHistory.insert(0, data); + isTextMsg = false; + isReplyMsg = false; + isAttachmentMsg = false; + isVoiceMsg = false; + sFileType = ""; + message.clear(); + notifyListeners(); + + List targetUsers =[]; + + for (GroupUserList element in userList) { + targetUsers.add(TargetUsers(isDelivered: false,isSeen: false, targetUserId: element.id, userAction: element.userAction, userStatus: element.userStatus)); + + } + + String chatData = + '{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId":$fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"groupId":$targetGroupId,"groupChatHistoryLineRequestList":${json.encode(targetUsers)},"chatReplyId": $chatReplyId,"conversationId":"${uuid.v4()}"}'; + + await chatHubConnection.invoke("AddGroupChatHistoryAsync", + args: [json.decode(chatData)]); + } + + void sendGroupChatMessage(BuildContext context, + {required int targetUserId, + required int userStatus, + required String userEmail, + required String targetUserName, + required List userList, + }) async { + if (isTextMsg && !isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { + logger.d("// Normal Text Message"); + if (message.text.isEmpty) { + return; + } + sendGroupChatToServer( + chatEventId: 1, + fileTypeId: null, + targetGroupId: targetUserId, + targetUserName: targetUserName, + isAttachment: false, + chatReplyId: null, + isReply: false, + isImageLoaded: false, + image: null, + isVoiceAttached: false, + userEmail: userEmail, + userStatus: userStatus, + userList:userList + ); + } else if (isTextMsg && !isAttachmentMsg && !isVoiceMsg && isReplyMsg) { + logger.d("// Text Message as Reply"); + if (message.text.isEmpty) { + return; + } + sendGroupChatToServer( + chatEventId: 1, + fileTypeId: null, + targetGroupId: targetUserId, + targetUserName: targetUserName, + chatReplyId: groupChatReplyData.first.groupChatHistoryId, + isAttachment: false, + isReply: true, + isImageLoaded: groupChatReplyData.first.isImageLoaded!, + image: groupChatReplyData.first.image, + isVoiceAttached: false, + voiceFile: null, + userEmail: userEmail, + userStatus: userStatus, + userList:userList + ); + } + // Attachment + else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { + logger.d("// Normal Image Message"); + Utils.showLoading(context); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile); + String? ext = getFileExtension(selectedFile.path); + Utils.hideLoading(context); + sendGroupChatToServer( + chatEventId: 2, + fileTypeId: getFileType(ext.toString()), + targetGroupId: targetUserId, + targetUserName: targetUserName, + isAttachment: true, + chatReplyId: null, + isReply: false, + isImageLoaded: true, + image: selectedFile.readAsBytesSync(), + isVoiceAttached: false, + userEmail: userEmail, + userStatus: userStatus, + userList:userList + ); + } else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) { + logger.d("// Image as Reply Msg"); + Utils.showLoading(context); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile); + String? ext = getFileExtension(selectedFile.path); + Utils.hideLoading(context); + sendGroupChatToServer( + chatEventId: 2, + fileTypeId: getFileType(ext.toString()), + + targetGroupId: targetUserId, + targetUserName: targetUserName, + isAttachment: true, + chatReplyId: repliedMsg.first.userChatHistoryId, + isReply: true, + isImageLoaded: true, + image: selectedFile.readAsBytesSync(), + isVoiceAttached: false, + userEmail: userEmail, + userStatus: userStatus, + userList:userList + ); + } + //Voice + + else if (!isTextMsg && !isAttachmentMsg && isVoiceMsg && !isReplyMsg) { + logger.d("// Normal Voice Message"); + + if (!isPause) { + path = await recorderController.stop(false); + } + if (kDebugMode) { + logger.i("path:" + path!); + } + File voiceFile = File(path!); + voiceFile.readAsBytesSync(); + _timer?.cancel(); + isPause = false; + isPlaying = false; + isRecoding = false; + Utils.showLoading(context); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile); + String? ext = getFileExtension(voiceFile.path); + Utils.hideLoading(context); + sendGroupChatToServer( + chatEventId: 2, + fileTypeId: getFileType(ext.toString()), + //, + targetGroupId: targetUserId, + targetUserName: targetUserName, + chatReplyId: null, + isAttachment: true, + isReply: isReplyMsg, + isImageLoaded: false, + voiceFile: voiceFile, + isVoiceAttached: true, + userEmail: userEmail, + userStatus: userStatus, + userList:userList + ); + notifyListeners(); + } else if (!isTextMsg && !isAttachmentMsg && isVoiceMsg && isReplyMsg) { + logger.d("// Voice as Reply Msg"); + + if (!isPause) { + path = await recorderController.stop(false); + } + if (kDebugMode) { + logger.i("path:" + path!); + } + File voiceFile = File(path!); + voiceFile.readAsBytesSync(); + _timer?.cancel(); + isPause = false; + isPlaying = false; + isRecoding = false; + + Utils.showLoading(context); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile); + String? ext = getFileExtension(voiceFile.path); + Utils.hideLoading(context); + sendGroupChatToServer( + chatEventId: 2, + fileTypeId: getFileType(ext.toString()), + targetGroupId: targetUserId, + targetUserName: targetUserName, + chatReplyId: null, + isAttachment: true, + isReply: isReplyMsg, + isImageLoaded: false, + voiceFile: voiceFile, + isVoiceAttached: true, + userEmail: userEmail, + userStatus: userStatus, + userList:userList + ); + notifyListeners(); + } + if (searchedChats != null) { + dynamic contain = searchedChats! + .where((ChatUser element) => element.id == targetUserId); + if (contain.isEmpty) { + List emails = []; + emails.add(await EmailImageEncryption().encrypt(val: userEmail)); + List chatImages = + await ChatApiClient().getUsersImages(encryptedEmails: emails); + searchedChats!.add( + ChatUser( + id: targetUserId, + userName: targetUserName, + unreadMessageCount: 0, + email: userEmail, + isImageLoading: false, + image: chatImages.first.profilePicture ?? "", + isImageLoaded: true, + isTyping: false, + isFav: false, + userStatus: userStatus, + // userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), + ), + ); + notifyListeners(); + } + } + } + + void sendChatMessage(BuildContext context, + {required int targetUserId, + required int userStatus, + required String userEmail, + required String targetUserName, + + }) async { if (kDebugMode) { print("====================== Values ============================"); print("Is Text " + isTextMsg.toString()); @@ -694,7 +1183,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { logger.d("// Normal Image Message"); Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer( @@ -713,7 +1203,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) { logger.d("// Image as Reply Msg"); Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer( @@ -748,7 +1239,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isPlaying = false; isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile); String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendChatToServer( @@ -782,7 +1274,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile); String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendChatToServer( @@ -801,11 +1294,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } if (searchedChats != null) { - dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); + dynamic contain = searchedChats! + .where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { List emails = []; emails.add(await EmailImageEncryption().encrypt(val: userEmail)); - List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); + List chatImages = + await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( id: targetUserId, @@ -818,7 +1313,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isTyping: false, isFav: false, userStatus: userStatus, - userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), + userLocalDownlaodedImage: await downloadImageLocal( + chatImages.first.profilePicture, targetUserId.toString()), ), ); notifyListeners(); @@ -848,7 +1344,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void selectImageToUpload(BuildContext context) { - ImageOptions.showImageOptionsNew(context, true, (String image, File file) async { + ImageOptions.showImageOptionsNew(context, true, + (String image, File file) async { if (checkFileSize(file.path)) { selectedFile = file; isAttachmentMsg = true; @@ -937,7 +1434,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { repliedMsg.add(data); notifyListeners(); } - + void groupChatReply(groupchathistory.GetGroupChatHistoryAsync data) { + groupChatReplyData = []; + data.isReplied = true; + isReplyMsg = true; + groupChatReplyData.add(data); + notifyListeners(); + } void closeMe() { repliedMsg = []; isReplyMsg = false; @@ -950,13 +1453,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return f.format(data); } - Future favoriteUser({required int userID, required int targetUserID, required bool fromSearch}) async { - fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().favUser(userID: userID, targetUserID: targetUserID); + Future favoriteUser( + {required int userID, + required int targetUserID, + required bool fromSearch}) async { + 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!) { user.isFav = favoriteChatUser.response!.isFav; - dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!); + dynamic contain = favUsersList!.where((ChatUser element) => + element.id == favoriteChatUser.response!.targetUserId!); if (contain.isEmpty) { favUsersList.add(user); } @@ -966,7 +1474,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUser user in chatUsersList!) { if (user.id == favoriteChatUser.response!.targetUserId!) { user.isFav = favoriteChatUser.response!.isFav; - dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!); + dynamic contain = favUsersList!.where((ChatUser element) => + element.id == favoriteChatUser.response!.targetUserId!); if (contain.isEmpty) { favUsersList.add(user); } @@ -985,8 +1494,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - Future unFavoriteUser({required int userID, required int targetUserID}) async { - fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().unFavUser(userID: userID, targetUserID: targetUserID); + Future unFavoriteUser( + {required int userID, required int targetUserID}) async { + fav.FavoriteChatUser favoriteChatUser = await ChatApiClient() + .unFavUser(userID: userID, targetUserID: targetUserID); if (favoriteChatUser.response != null) { for (ChatUser user in searchedChats!) { @@ -1056,7 +1567,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { favUsersList.clear(); searchedChats?.clear(); pChatHistory?.clear(); - // callP.stopListeners(); + uGroups?.clear(); + searchGroup?.clear(); chatHubConnection.stop(); AppState().chatDetails = null; } @@ -1090,12 +1602,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { emails.add(await EmailImageEncryption().encrypt(val: element.email!)); } - List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); + List chatImages = + await ChatApiClient().getUsersImages(encryptedEmails: emails); for (ChatUser user in searchedChats!) { for (ChatUserImageModel uImage in chatImages) { if (user.email == uImage.email) { user.image = uImage.profilePicture ?? ""; - user.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, user.id.toString()); + user.userLocalDownlaodedImage = await downloadImageLocal( + uImage.profilePicture, user.id.toString()); user.isImageLoading = false; user.isImageLoaded = true; } @@ -1105,7 +1619,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUserImageModel uImage in chatImages) { if (favUser.email == uImage.email) { favUser.image = uImage.profilePicture ?? ""; - favUser.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, favUser.id.toString()); + favUser.userLocalDownlaodedImage = await downloadImageLocal( + uImage.profilePicture, favUser.id.toString()); favUser.isImageLoading = false; favUser.isImageLoaded = true; } @@ -1122,7 +1637,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else { await deleteFile(userID); Uint8List decodedBytes = base64Decode(encodedBytes); - Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); + Directory appDocumentsDirectory = + await getApplicationDocumentsDirectory(); String dirPath = '${appDocumentsDirectory.path}/chat_images'; if (!await Directory(dirPath).exists()) { await Directory(dirPath).create(); @@ -1145,7 +1661,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future downChatMedia(Uint8List bytes, String ext) async { String dir = (await getApplicationDocumentsDirectory()).path; - File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + File file = File( + "$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); await file.writeAsBytes(bytes); return file.path; } @@ -1168,10 +1685,20 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - Future getChatMedia(BuildContext context, {required String fileName, required String fileTypeName, required int fileTypeID}) async { + Future getChatMedia(BuildContext context, + {required String fileName, + required String fileTypeName, + required int fileTypeID}) async { Utils.showLoading(context); - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) { - Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName)); + if (fileTypeID == 1 || + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 || + fileTypeID == 2) { + Uint8List encodedString = await ChatApiClient().downloadURL( + fileName: fileName, + fileTypeDescription: getFileTypeDescription(fileTypeName)); try { String path = await downChatMedia(encodedString, fileTypeName ?? ""); Utils.hideLoading(context); @@ -1193,10 +1720,19 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return ""; } - void userTypingInvoke({required int currentUser, required int reciptUser}) async { - await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]); + void userTypingInvoke( + {required int currentUser, required int reciptUser}) async { + await chatHubConnection + .invoke("UserTypingAsync", args: [reciptUser, currentUser]); + } + void groupTypingInvoke( + {required GroupResponse groupDetails, required int groupId}) async { + var data = json.decode(json.encode(groupDetails.groupUserList)); + await chatHubConnection + .invoke("GroupTypingAsync", args: ["${groupDetails.adminUser!.userName}",data, groupId ]); } + //////// Audio Recoding Work //////////////////// Future initAudio({required int receiverId}) async { @@ -1210,7 +1746,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await Directory(dirPath).create(); await File('$dirPath/.nomedia').create(); } - path = "$dirPath/${AppState().chatDetails!.response!.id}-$receiverID-${DateTime.now().microsecondsSinceEpoch}.aac"; + path = + "$dirPath/${AppState().chatDetails!.response!.id}-$receiverID-${DateTime.now().microsecondsSinceEpoch}.aac"; recorderController = RecorderController() ..androidEncoder = AndroidEncoder.aac ..androidOutputFormat = AndroidOutputFormat.mpeg4 @@ -1340,15 +1877,19 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return numberStr; } - Future downChatVoice(Uint8List bytes, String ext, SingleUserChatModel data) async { + Future downChatVoice( + Uint8List bytes, String ext, SingleUserChatModel data) async { File file; try { - String dirPath = '${(await getApplicationDocumentsDirectory()).path}/chat_audios'; + String dirPath = + '${(await getApplicationDocumentsDirectory()).path}/chat_audios'; if (!await Directory(dirPath).exists()) { await Directory(dirPath).create(); await File('$dirPath/.nomedia').create(); } - file = File("$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}" + ext); + file = File( + "$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}" + + ext); await file.writeAsBytes(bytes); } catch (e) { if (kDebugMode) { @@ -1360,10 +1901,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void scrollToMsg(SingleUserChatModel data) { - if (data.userChatReplyResponse != null && data.userChatReplyResponse!.userChatHistoryId != null) { - int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == data.userChatReplyResponse!.userChatHistoryId); + if (data.userChatReplyResponse != null && + data.userChatReplyResponse!.userChatHistoryId != null) { + int index = userChatHistory.indexWhere((SingleUserChatModel element) => + element.userChatHistoryId == + data.userChatReplyResponse!.userChatHistoryId); if (index >= 1) { - double contentSize = scrollController.position.viewportDimension + scrollController.position.maxScrollExtent; + double contentSize = scrollController.position.viewportDimension + + scrollController.position.maxScrollExtent; double target = contentSize * index / userChatHistory.length; scrollController.position.animateTo( target, @@ -1395,14 +1940,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoading: false, image: element.eMPLOYEEIMAGE ?? "", isImageLoaded: element.eMPLOYEEIMAGE == null ? false : true, - userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null ? null : await downloadImageLocal(element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), + userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null + ? null + : await downloadImageLocal( + element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), ), ); } } } } else { - getEmployeeSubordinatesList = await MyTeamApiClient().getEmployeeSubordinates("", "", ""); + getEmployeeSubordinatesList = + await MyTeamApiClient().getEmployeeSubordinates("", "", ""); AppState().setemployeeSubordinatesList = getEmployeeSubordinatesList; for (GetEmployeeSubordinatesList element in getEmployeeSubordinatesList) { if (element.eMPLOYEEEMAILADDRESS != null) { @@ -1420,7 +1969,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoading: false, image: element.eMPLOYEEIMAGE ?? "", isImageLoaded: element.eMPLOYEEIMAGE == null ? false : true, - userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null ? null : await downloadImageLocal(element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), + userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null + ? null + : await downloadImageLocal( + element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), ), ); } @@ -1484,4 +2036,86 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } return Material.TextDirection.ltr; } + + void openChatByNoti(BuildContext context) async { + SingleUserChatModel nUser = SingleUserChatModel(); + Utils.saveStringFromPrefs("isAppOpendByChat", "false"); + if (await Utils.getStringFromPrefs("notificationData") != "null") { + nUser = SingleUserChatModel.fromJson( + jsonDecode(await Utils.getStringFromPrefs("notificationData"))); + Utils.saveStringFromPrefs("notificationData", "null"); + Future.delayed(const Duration(seconds: 2)); + for (ChatUser user in searchedChats!) { + if (user.id == nUser.targetUserId) { + Navigator.pushNamed(context, AppRoutes.chatDetailed, + arguments: ChatDetailedScreenParams(user, false)); + return; + } + } + } + Utils.saveStringFromPrefs("notificationData", "null"); + } + + //group chat functions added here + + void filterGroups(String value) async { + // filter function added here. + List tmp = []; + if (value.isEmpty || value == "") { + tmp = userGroups.groupresponse!; + } else { + for (groups.GroupResponse element in uGroups!) { + if (element.groupName!.toLowerCase().contains(value.toLowerCase())) { + tmp.add(element); + } + } + } + uGroups = tmp; + notifyListeners(); + } + + Future deleteGroup(GroupResponse groupDetails) async { + isLoading = true; + await ChatApiClient().deleteGroup(groupDetails.groupId); + userGroups = await ChatApiClient().getGroupsByUserId(); + uGroups = userGroups.groupresponse; + isLoading = false; + notifyListeners(); + } + + Future getGroupChatHistory(groups.GroupResponse groupDetails) async { + isLoading = true; + groupChatHistory = await ChatApiClient().getGroupChatHistory( + groupDetails.groupId, + groupDetails.groupUserList as List); + + isLoading = false; + + notifyListeners(); + } + + void updateGroupAdmin(int? groupId, List groupUserList) async { + isLoading = true; + await ChatApiClient().updateGroupAdmin(groupId, groupUserList); + isLoading = false; + notifyListeners(); + } + + Future addGroupAndUsers(createGroup.CreateGroupRequest request) async { + isLoading = true; + var groups = await ChatApiClient().addGroupAndUsers(request); + userGroups.groupresponse! + .add(GroupResponse.fromJson(json.decode(groups)['response'])); + + isLoading = false; + notifyListeners(); + } + Future updateGroupAndUsers(createGroup.CreateGroupRequest request) async { + isLoading = true; + await ChatApiClient().updateGroupAndUsers(request); + userGroups = await ChatApiClient().getGroupsByUserId(); + uGroups = userGroups.groupresponse; + isLoading = false; + notifyListeners(); + } } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 5eac532..0e18544 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -278,7 +278,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { getMenuEntriesList.add(activeDirectoryEntry); list.add(GetMenuEntriesList(requestType: "ITG_FORMS", prompt: LocaleKeys.itgForms.tr(), menuName: 'ITG_FORMS')); - list.add(GetMenuEntriesList(requestType: "MY_DOCUMENTS", prompt: LocaleKeys.myDocuments.tr(), menuName: 'MY_DOCUMENTS')); } menus.add(Menus(getMenuEntriesList[i], list)); diff --git a/lib/ui/app_update_screen.dart b/lib/ui/app_update_screen.dart index 4a769c3..b05f436 100644 --- a/lib/ui/app_update_screen.dart +++ b/lib/ui/app_update_screen.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:in_app_update/in_app_update.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'; @@ -37,16 +38,38 @@ class _UnsafeDeviceScreenState extends State { dynamicParams.toString().toText14(isCenter: true).paddingOnly(left: 20.0, right: 20.0), 21.height, DefaultButton(LocaleKeys.ok.tr(), () async { - if (Platform.isAndroid || Platform.isIOS) { - var appId = Platform.isAndroid ? 'hmg.cloudSolutions.mohem' : '1468856602'; + if (Platform.isAndroid) { + // _launchURL("https://play.google.com/store/apps/details?id=com.ejada.hmg"); + InAppUpdate.checkForUpdate().then((info) { + print("checkForUpdate!!!"); + print(info.toString()); + if (info.immediateUpdateAllowed) { + print("Immediate Allowed!!!"); + InAppUpdate.performImmediateUpdate().then((value) {}).catchError((e) => print(e.toString())); + } + }).catchError((e) { + print(e.toString()); + }); + } + if (Platform.isIOS) { var url = Uri.parse( - Platform.isAndroid ? "market://details?id=$appId" : "https://apps.apple.com/app/id$appId", + "https://apps.apple.com/app/id1468856602", ); launchUrl( url, mode: LaunchMode.externalApplication, ); } + // if (Platform.isAndroid || Platform.isIOS) { + // var appId = Platform.isAndroid ? 'hmg.cloudSolutions.mohem' : '1468856602'; + // var url = Uri.parse( + // Platform.isAndroid ? "market://details?id=$appId" : "https://apps.apple.com/app/id$appId", + // ); + // launchUrl( + // url, + // mode: LaunchMode.externalApplication, + // ); + // } }).paddingAll(24) ], ), diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 648e758..a31cfb4 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/provider/chat_call_provider.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/chat/group_chat.dart'; import 'package:mohem_flutter_app/ui/chat/my_team_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; @@ -51,6 +52,7 @@ class _ChatHomeState extends State { data.getUserAutoLoginToken().whenComplete(() async { await data.buildHubConnection(context: context, ccProvider: callProvider); data.getUserRecentChats(); + }); return; } @@ -89,8 +91,9 @@ class _ChatHomeState extends State { child: Row( children: [ myTab(LocaleKeys.mychats.tr(), 0), - myTab(LocaleKeys.favorite.tr(), 1), - AppState().getempStatusIsManager ? myTab(LocaleKeys.myTeam.tr(), 2) : const SizedBox(), + // myTab(LocaleKeys.group.tr(), 1), + myTab(LocaleKeys.favorite.tr(), 2), + AppState().getempStatusIsManager ? myTab(LocaleKeys.myTeam.tr(), 3) : const SizedBox(), ], ), ), @@ -104,6 +107,7 @@ class _ChatHomeState extends State { }, children: [ ChatHomeScreen(), + // GropChatHomeScreen(), ChatFavoriteUsersScreen(), AppState().getempStatusIsManager ? const MyTeamScreen() : const SizedBox(), ], diff --git a/lib/ui/chat/create_group.dart b/lib/ui/chat/create_group.dart new file mode 100644 index 0000000..43b2635 --- /dev/null +++ b/lib/ui/chat/create_group.dart @@ -0,0 +1,699 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.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'; +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'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/chat/create_group_request.dart'; +import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' + as groups; +import 'package:mohem_flutter_app/models/get_action_history_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; +import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; +import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; +import 'package:provider/provider.dart'; + +class CreateGroupBottomSheet extends StatefulWidget { + int? notificationID; + String title, apiMode; + List? actionHistoryList; + Function(ReplacementList) onSelectEmployee; + bool fromChat; + groups.GroupResponse groupDetails; + + CreateGroupBottomSheet({ + Key? key, + required this.title, + required this.apiMode, + this.notificationID, + this.actionHistoryList, + required this.onSelectEmployee, + required this.fromChat, + required this.groupDetails, + }) : super(key: key); + + @override + State createState() => _CreateGroupBottomSheetState(); +} + +class _CreateGroupBottomSheetState extends State { + TextEditingController username = TextEditingController(); + ScrollController sc = ScrollController(); + bool isAudioCall = true; + bool isVideoCall = true; + bool isAttachments = true; + bool isShareScreen = true; + String searchText = ""; + String groupName = ""; + List? optionsList = [ + LocaleKeys.fullName.tr(), + LocaleKeys.username.tr(), + LocaleKeys.endDate.tr(), + ]; + List? favUsersList; + + List? replacementList; + List? favouriteUserList; + List? nonFavouriteUserList; + + // Chat Items + late ChatProviderModel provider; + + int _selectedSearchIndex = 0; + List selectedUsers = []; + + void fetchUserByInput({bool isNeedLoading = true}) async { + try { + Utils.showLoading(context); + replacementList = await WorkListApiClient().searchUserByInput( + userName: _selectedSearchIndex == 0 ? searchText : "", + userId: _selectedSearchIndex == 1 ? searchText : "", + email: _selectedSearchIndex == 2 ? searchText : "", + ); + favouriteUserList = replacementList + ?.where((ReplacementList element) => element.isFavorite ?? false) + .toList(); + nonFavouriteUserList = replacementList + ?.where((ReplacementList element) => !(element.isFavorite ?? false)) + .toList(); + Utils.hideLoading(context); + setState(() {}); + } catch (e) { + Utils.hideLoading(context); + Utils.handleException(e, context, null); + } + + if (isNeedLoading) Utils.hideLoading(context); + setState(() {}); + return null; + } + + void fetchChatUser({bool isNeedLoading = true}) async { + if (provider.pageNo == 1) provider.chatUsersList!.clear(); + try { + Utils.showLoading(context); + await ChatApiClient() + .getChatMemberFromSearch(searchText, + AppState().chatDetails!.response!.id!, provider.pageNo) + .then((ChatUserModel value) { + if (value.response != null) { + if (provider.pageNo == 1) { + provider.chatUsersList = value.response; + } else { + print("--------------------------Added More----------------------"); + provider.chatUsersList!.addAll(value.response!); + } + } + }); + provider.chatUsersList!.removeWhere((ChatUser element) => + element.id == AppState().chatDetails!.response!.id); + Utils.hideLoading(context); + setState(() {}); + } catch (e) { + Utils.hideLoading(context); + Utils.handleException(e, context, null); + } + if (isNeedLoading) Utils.hideLoading(context); + setState(() {}); + return null; + } + + void scrollListener() async { + if (sc.position.pixels == sc.position.maxScrollExtent) { + provider.pageNo++; + logger.w(provider.chatUsersList!.length); + logger.w(provider.pageNo); + fetchChatUser(); + } + } + + @override + void initState() { + super.initState(); + sc.addListener(scrollListener); + provider = Provider.of(context, listen: false); + if (widget.groupDetails.groupName !=null) { + setState(() { + groupName = widget.groupDetails.groupName!; + isAudioCall = widget.groupDetails.canAudioC!; + isVideoCall = widget.groupDetails.canVideoC!; + isAttachments = widget.groupDetails.canAttach!; + isShareScreen = widget.groupDetails.canShareS!; + for (groups.GroupUserList items in widget.groupDetails.groupUserList!) { + { + selectedUsers.add(ChatUser.fromJson(items.toJson())); + } + } + }); + } + } + + @override + void dispose() { + super.dispose(); + provider.chatUsersList = []; + provider.pageNo = 1; + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + height: MediaQuery.of(context).size.height - 100, + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.title.toText24(isBold: true), + 21.height, + Row( + children: [ + DynamicTextFieldWidget( + LocaleKeys.groupName.tr(), + groupName.isEmpty ? LocaleKeys.enterGroupNamePlease.tr() : groupName, + inputAction: TextInputAction.done, + onChange: (String text) { + groupName = text; + setState(() {}); + }, + ).expanded, + ], + ), + + //11.height, + Row( + children: [ + SizedBox( + height: 35, + child: CheckboxListTile( + contentPadding: EdgeInsets.zero, + title: LocaleKeys.audioCall.tr().toText10(), + + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + side: BorderSide( + width: 1.5, + color: Theme.of(context).unselectedWidgetColor), + + value: isAudioCall, + onChanged: (bool? newValue) { + setState(() { + isAudioCall = newValue!; + }); + }, + controlAffinity: ListTileControlAffinity + .leading, // <-- leading Checkbox + )).expanded, + SizedBox( + height: 35, + child: CheckboxListTile( + contentPadding: EdgeInsets.zero, + title: LocaleKeys.videoCall.tr().toText10(), + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + value: isVideoCall, + onChanged: (bool? newValue) { + setState(() { + isVideoCall = newValue!; + }); + }, + controlAffinity: ListTileControlAffinity + .leading, // <-- leading Checkbox + )).expanded + ], + ), + Row( + children: [ + SizedBox( + height: 35, + child: CheckboxListTile( + contentPadding: EdgeInsets.zero, + title:LocaleKeys.attachments.tr().toText10(), + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + value: isAttachments, + onChanged: (bool? newValue) { + setState(() { + isAttachments = newValue!; + }); + }, + controlAffinity: ListTileControlAffinity + .leading, // <-- leading Checkbox + )).expanded, + SizedBox( + height: 35, + child: CheckboxListTile( + contentPadding: EdgeInsets.zero, + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + title:LocaleKeys.shareScreen.tr().toText10(), + value: isShareScreen, + onChanged: (bool? newValue) { + setState(() { + isShareScreen = newValue!; + }); + }, + controlAffinity: ListTileControlAffinity + .leading, // <-- leading Checkbox + )).expanded + ], + ), + 11.height, + LocaleKeys.userSearch.tr().toText16(), + 11.height, + Row( + children: [ + radioOption(widget.fromChat ? LocaleKeys.userId.tr() : LocaleKeys.name.tr(), 0, + _selectedSearchIndex), + radioOption(LocaleKeys.userName.tr(), 1, _selectedSearchIndex), + radioOption(LocaleKeys.email.tr(), 2, _selectedSearchIndex), + ], + ), + 14.height, + Row( + children: [ + DynamicTextFieldWidget( + LocaleKeys.search.tr(), + LocaleKeys.searchByUserName.tr(), + inputAction: TextInputAction.done, + suffixIconData: Icons.search, + onChange: (String text) { + searchText = text; + setState(() {}); + }, + ).expanded, + IconButton( + constraints: const BoxConstraints(), + onPressed: () async { + provider.chatUsersList!.clear(); + provider.pageNo =1; + await SystemChannels.textInput + .invokeMethod('TextInput.hide'); + widget.fromChat ? fetchChatUser() : fetchUserByInput(); + }, + icon: const Icon(Icons.search), + ) + ], + ), + if (replacementList != null) + replacementList!.isEmpty + ? Utils.getNoDataWidget(context).expanded + : ListView( + physics: const BouncingScrollPhysics(), + padding: EdgeInsets.only(top: 21, bottom: 8), + children: [ + if (favouriteUserList?.isNotEmpty ?? false) ...[ + LocaleKeys.favorite.tr().toText16(), + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext cxt, int index) => + employeeItemView(favouriteUserList![index]), + separatorBuilder: + (BuildContext cxt, int index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: favouriteUserList?.length ?? 0), + 12.height, + ], + if (nonFavouriteUserList?.isNotEmpty ?? false) ...[ + "Related".toText16(), + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext cxt, int index) => + employeeItemView( + nonFavouriteUserList![index]), + separatorBuilder: + (BuildContext cxt, int index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: nonFavouriteUserList?.length ?? 0), + ], + ], + ).expanded, + selectedUsers!.isNotEmpty + ? SizedBox( + height: 95, + child: ListView.builder( + physics: const ClampingScrollPhysics(), + scrollDirection: Axis.horizontal, + itemCount: selectedUsers!.length, + itemBuilder: (BuildContext context, int index2) { + return Stack(children: [ + Column( + children: [ + 12.height, + Stack(children: [ + Container( + padding:const EdgeInsets.all(5), + child: SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + )), + Positioned( + right: 0, + top: 0, + child: InkWell( + child: SvgPicture.asset( + 'assets/icons/close.svg', + height:15, + width:15 + ), + onTap: () { + setState(() { + // provider.chatUsersList![index] + // .isChecked = false; + + List user = provider + .chatUsersList! + .where((ChatUser value) => + value.userName == + selectedUsers[index2] + .userName) + .toList(); + if (user.isNotEmpty) { + user.first.isChecked = false; + } + selectedUsers.remove( + selectedUsers[index2]); + }); + }, + )) + ],), + (selectedUsers![index2] + .userName! + .replaceFirst(".", " ") + .capitalizeFirstofEach ?? + "") + .toText12(color: MyColors.darkTextColor) + .paddingOnly(left: 5, top: 5), + selectedUsers![index2].isTyping! + ? 'Typing...' + .toText10( + color: MyColors.textMixColor, + ) + .paddingOnly(left: 5.0) + : const SizedBox() + ], + ), + + + + // IconButton(onPressed: (){}, icon: const Icon(Icons.close_outlined, color: Colors.red, size: 20)), + + ]); + })) + : 0.height, + + if (widget.fromChat) + if (provider.chatUsersList != null && widget.fromChat) + provider.chatUsersList!.isEmpty + ? Column( + children: [ + 20.height, + Utils.getNoDataWidget(context), + ], + ) + : ListView.separated( + itemCount: provider.chatUsersList!.length, + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + controller: sc, + padding: const EdgeInsets.only(bottom: 80.0, top: 20), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + 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: provider + .chatUsersList![index] + .userStatus == + 1 + ? MyColors.green2DColor + : Colors.red, + ), + ).circle(10), + ) + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + (provider.chatUsersList![index].userName! + .replaceFirst(".", " ") + .capitalizeFirstofEach ?? + "") + .toText14( + color: MyColors.darkTextColor) + .paddingOnly(left: 11, top: 13), + provider.chatUsersList![index].isTyping! + ? 'Typing...' + .toText10( + color: MyColors.textMixColor, + ) + .paddingOnly(left: 11.0) + : const SizedBox() + ], + ).expanded, + SizedBox( + width: 60, + child: Row( + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + if (provider.chatUsersList![index] + .unreadMessageCount! > + 0) + Container( + alignment: Alignment.center, + width: 18, + height: 18, + decoration: const BoxDecoration( + color: MyColors.redColor, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: (provider + .chatUsersList![index] + .unreadMessageCount! + .toString()) + .toText10( + color: MyColors.white, + ) + .center, + ).paddingOnly(right: 10).center, + Checkbox( + value: provider + .chatUsersList![index].isChecked, + shape: CircleBorder(), + onChanged: (bool? value) { + setState(() { + provider.chatUsersList![index] + .isChecked = value; + if (provider.chatUsersList![index] + .isChecked == + true) { + selectedUsers.add(provider + .chatUsersList![index]); + } else { + selectedUsers.remove(provider + .chatUsersList![index]); + } + }); + }, + ) + ], + ), + ), + ], + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => + const Divider(color: MyColors.lightGreyE5Color) + .paddingOnly(left: 59), + ).expanded, + ], + ).paddingOnly(left: 21, right: 21, bottom: 0, top: 21).expanded, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + DefaultButton( + LocaleKeys.cancel.tr(), + () { + Navigator.pop(context); + provider.chatUsersList = []; + provider.pageNo = 1; + }, + textColor: MyColors.grey3AColor, + colors: const [ + Color(0xffE6E6E6), + Color(0xffE6E6E6), + ], + ).paddingOnly(left: 14, right: 14, bottom: 15, top: 10).expanded, + DefaultButton( + LocaleKeys.submit.tr(), + () { + // Navigator.pop(context); + // provider.chatUsersList = []; + // provider.pageNo = 1; + createGroup(); + }, + textColor: MyColors.whiteColor, + colors: const [ + Color(0xff32D892), + Color(0xff1AB170), + ], + ).paddingOnly(left: 15, right: 15, bottom: 15, top: 10).expanded, + ], + ) + ], + ), + ); + } + + Widget employeeItemView(ReplacementList replacement) { + return InkWell( + onTap: () { + Navigator.pop(context); + widget.onSelectEmployee(replacement); + }, + child: SizedBox( + height: 50, + child: Row( + children: [ + CircularAvatar( + url: replacement.employeeImage ?? "", + height: 30, + width: 30, + isImageBase64: true, + ), + 16.width, + Expanded( + child: (replacement.employeeDisplayName ?? "").toText12(), + ), + Icon(Icons.star, + size: 16, + color: replacement.isFavorite! + ? MyColors.yellowFavColor + : MyColors.borderCEColor), + ], + ), + ), + ); + } + + Widget radioOption(String title, int value, int groupValue) { + return Row( + children: [ + Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all(color: MyColors.borderColor, width: 1), + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), + ), + padding: const EdgeInsets.all(4), + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: value == groupValue + ? MyColors.grey3AColor + : Colors.transparent, + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), + ), + ), + ), + 9.width, + title.toText12(color: MyColors.grey57Color) + ], + ).onPress(() { + _selectedSearchIndex = value; + setState(() {}); + }).expanded; + } + + void createGroup() async { + RegExp validCharacters = RegExp(r'^[a-zA-Z0-9_\-=@,\.;]+$'); + if (!validCharacters.hasMatch(groupName)) { + Utils.showToast(LocaleKeys.enterGroupName.tr()); + } else if (groupName.length < 10) { + Utils.showToast(LocaleKeys.groupNameshouldbe.tr()); + } else { + List? mainUsers = []; + ChatUser admin = + ChatUser.fromJson(AppState().chatDetails!.response!.toJson()); + admin.isAdmin = true; + admin.userStatus = 2; + admin.unreadMessageCount = 0; + admin.totalCount = 0; + mainUsers.add(admin); + CreateGroupRequest request = CreateGroupRequest( + groupUserList: [...selectedUsers, ...mainUsers].toList(), + canArchive: false, + isMeeting: false, + canShareS: isShareScreen, + canAudioC: isAudioCall, + canAttach: isAttachments, + canVideoC: isVideoCall, + groupName: groupName, + adminUserId: AppState().chatDetails!.response!.id); + + if(widget.groupDetails!.groupId !=null){ + request.groupId =widget.groupDetails!.groupId; + await provider.updateGroupAndUsers(request); + }else { + await provider.addGroupAndUsers(request); + } + Navigator.pop(context); + } + } +} diff --git a/lib/ui/chat/group_chat.dart b/lib/ui/chat/group_chat.dart new file mode 100644 index 0000000..35b4c5c --- /dev/null +++ b/lib/ui/chat/group_chat.dart @@ -0,0 +1,307 @@ +import 'package:easy_localization/easy_localization.dart'; +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/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.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/models/chat/get_group_chat_history.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'; +import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; +import 'package:mohem_flutter_app/ui/chat/create_group.dart'; +import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart'; +import 'package:mohem_flutter_app/ui/chat/manage_group.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'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class GropChatHomeScreen extends StatefulWidget { + const GropChatHomeScreen({Key? key}) : super(key: key); + + @override + State createState() => _GropChatHomeScreenState(); +} + +class _GropChatHomeScreenState extends State { + TextEditingController search = TextEditingController(); + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + search.clear(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.white, + body: Consumer( + builder: (BuildContext context, ChatProviderModel m, Widget? child) { + return m.isLoading + ? ChatHomeShimmer( + isDetailedScreen: false, + ) + : Column( + children: [ + TextField( + controller: m.searchGroup, + style: const TextStyle( + color: MyColors.darkTextColor, + fontWeight: FontWeight.w500, + fontSize: 12), + onChanged: (String val) { + m.filterGroups(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.searchGroup.tr(), + hintStyle: const TextStyle( + color: MyColors.lightTextColor, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w500, + fontSize: 12), + filled: true, + fillColor: MyColors.greyF7Color, + 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.uGroups != null) + ListView.separated( + itemCount: m.uGroups!.length, + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.only(bottom: 80.0), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + child: Row( + children: [ + Container( + alignment: Alignment.center, + width: 48, + height: 48, + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + border: Border.all( + width: 1, color: Colors.black), + ), + child: SvgPicture.asset( + "assets/images/chat-group.svg", + )), + Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + (m.uGroups![index] + .groupName! + .toText14( + color: MyColors.darkTextColor) + .paddingOnly(left: 11, top: 16))!, + ]), + Align( + alignment: Alignment.centerRight, + + child: PopupMenuButton( + onSelected: (String value){ + goToSelected(m.uGroups![index], m, value); + + }, + itemBuilder: (context) => [ + PopupMenuItem( + value: '1', + enabled: m.uGroups![index].isAdmin ?? false, + child: (LocaleKeys.edit + .tr() + .toText14(color: m.userGroups?.groupresponse![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor) + .paddingOnly(left: 11, top: 16))), + PopupMenuItem( + value: '2', + enabled: m.uGroups![index].isAdmin ?? false, + child: (LocaleKeys.delete + .tr() + .toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor) + .paddingOnly(left: 11, top: 16))), + PopupMenuItem( + value: '3', + enabled: m.uGroups![index].isAdmin ?? false, + onTap: () { + + }, + child: (LocaleKeys.manage + .tr() + .toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor) + .paddingOnly(left: 11, top: 16))), + PopupMenuItem( + value: '4', + child: (LocaleKeys.members + .tr() + .toText14(color: MyColors.darkTextColor) + .paddingOnly(left: 11, top: 16))), + ], + ) + + + ) + .expanded + ], + ), + ).onPress(() { + chatDetails(m.uGroups![index], m,); + // Navigator.pushNamed( + // context, + // AppRoutes.chatDetailed, + // arguments: ChatDetailedScreenParams( + // m.searchedChats![index], false), + // ).then((Object? value) { + // m.clearSelections(); + // m.notifyListeners(); + // }); + }); + }, + separatorBuilder: (BuildContext context, int index) => + const Divider(color: MyColors.black) + .paddingOnly(left: 59), + ).expanded, + ], + ).paddingOnly(left: 21, right: 21); + }, + ), + floatingActionButton: FloatingActionButton( + child: Container( + width: 60, + height: 60, + decoration: const BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + transform: GradientRotation(.46), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + ), + child: const Icon( + Icons.add, + size: 30, + color: MyColors.white, + ), + ), + onPressed: () async { + + showMyBottomSheet( + context, + callBackFunc: () {}, + child: CreateGroupBottomSheet( + title:LocaleKeys.addUsers.tr(), + apiMode: LocaleKeys.delegate.tr(), + fromChat: true, + onSelectEmployee: (ReplacementList _selectedEmployee) {}, + groupDetails:GroupResponse(), + ), + ); + }, + ), + ); + } + + OutlineInputBorder fieldBorder({required double radius, required int color}) { + return OutlineInputBorder( + borderRadius: BorderRadius.circular(radius), + borderSide: BorderSide( + color: Color(color), + ), + ); + } + +void goToSelected(GroupResponse? groupDetails, ChatProviderModel m, String value) { + switch(value) { + case '1': + editGroup(groupDetails, m); + break; + case '2': + deleteGroup(groupDetails, m, context); + break; + case '3': + Navigator.pushNamed(context, + AppRoutes.manageGroup, + arguments: groupDetails , + ); + break; + case '4': + Navigator.pushNamed(context, + AppRoutes.groupMembers, + arguments: groupDetails!.groupUserList, + ); + break; + } + } + void deleteGroup( + GroupResponse? groupDetails, ChatProviderModel m, BuildContext context) { + groupDetails!.groupUserList; + Utils.confirmDialog( + context, + LocaleKeys.areYouSureWantTodelete.tr(), + onTap: () { + Navigator.pop(context); + m.deleteGroup(groupDetails); + }, + ); + } + + Future chatDetails(GroupResponse? groupDetails, ChatProviderModel m) async { + + // await m.getGroupChatHistory(groupDetails!); + + Navigator.pushNamed(context, + AppRoutes.groupChatDetailed, + arguments: + GroupChatDetailedScreenParams( + groupDetails, + false)); + } + Future editGroup(GroupResponse? groupDetails, ChatProviderModel m) async { + showMyBottomSheet( + context, + callBackFunc: () {}, + child: CreateGroupBottomSheet( + title:LocaleKeys.editGroups.tr(), + apiMode: LocaleKeys.delegate.tr(), + fromChat: true, + onSelectEmployee: (ReplacementList _selectedEmployee) {}, + groupDetails: groupDetails!, + ), + ); + + } +} diff --git a/lib/ui/chat/group_chat_bubble.dart b/lib/ui/chat/group_chat_bubble.dart new file mode 100644 index 0000000..69a50df --- /dev/null +++ b/lib/ui/chat/group_chat_bubble.dart @@ -0,0 +1,643 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:just_audio/just_audio.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/colors.dart'; +import 'package:mohem_flutter_app/classes/my_custom_stream.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart'; +import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_full_image_preview.dart'; +import 'package:mohem_flutter_app/ui/chat/common.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:rxdart/rxdart.dart'; + +class GroupChatBubble extends StatelessWidget { + GroupChatBubble({Key? key, required this.dateTime, required this.cItem}) + : super(key: key); + final String dateTime; + final GetGroupChatHistoryAsync cItem; + + bool isCurrentUser = false; + + bool isSeen = false; + + bool isReplied = false; + + bool isVoice = false; + + int? fileTypeID; + + String? fileTypeName; + + late ChatProviderModel provider; + + String? fileTypeDescription; + + bool isDelivered = false; + + String userName = ''; + + late Offset screenOffset; + + void makeAssign() { + isCurrentUser = cItem.currentUserId == AppState().chatDetails!.response!.id + ? true + : false; + isSeen = cItem.isSeen == true ? true : false; + isReplied = cItem.groupChatReplyResponse != null ? true : false; + // isVoice = cItem.fileTypeId == 13 && cItem.voiceController != null ? true : false; + fileTypeID = cItem.fileTypeId; + fileTypeName = cItem.fileTypeResponse != null + ? cItem.fileTypeResponse!.fileTypeName + : ""; + fileTypeDescription = cItem.fileTypeResponse != null + ? cItem.fileTypeResponse!.fileTypeDescription + : ""; + isDelivered = cItem.currentUserId == AppState().chatDetails!.response!.id && + cItem.isDelivered == true + ? true + : false; + userName = AppState().chatDetails!.response!.userName == + cItem.currentUserName.toString() + ? "You" + : cItem.currentUserName.toString(); + } + + void playVoice( + BuildContext context, { + required SingleUserChatModel data, + }) async { + if (data.voice != null && data.voice!.existsSync()) { + if (Platform.isIOS) { + Duration? duration = await data.voiceController! + .setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); + await data.voiceController!.seek(duration); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.setVolume(1.0); + await data.voiceController!.load(); + data.voiceController!.play(); + } else { + await data.voiceController!.setFilePath(data!.voice!.path); + Duration? duration = await data.voiceController!.load(); + await data.voiceController!.seek(duration); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.play(); + } + } else { + Utils.showLoading(context); + Uint8List encodedString = await ChatApiClient().downloadURL( + fileName: data.contant!, + fileTypeDescription: provider.getFileTypeDescription( + data.fileTypeResponse!.fileTypeName ?? "")); + // try { + File sFile = await provider.downChatVoice( + encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); + if (sFile.path.isEmpty) { + logger.d("Path Is Emptyyyyyyy"); + } else { + logger.d("Path Exsists"); + } + data.voice = sFile; + if (Platform.isIOS) { + logger.d("isIOS"); + Duration? duration = await data.voiceController! + .setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); + await data.voiceController!.seek(duration); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.setVolume(1.0); + await data.voiceController!.load(); + Utils.hideLoading(context); + data.voiceController!.play(); + } else { + Duration? duration = + await data.voiceController!.setFilePath(sFile.path); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.seek(duration); + Utils.hideLoading(context); + await data.voiceController!.play(); + } + } + } + + void pausePlaying(BuildContext context, + {required SingleUserChatModel data}) async { + await data.voiceController!.pause(); + } + + void rePlay(BuildContext context, {required SingleUserChatModel data}) async { + if (data.voice != null && data.voice!.existsSync()) { + await data.voiceController!.seek(Duration.zero); + await data.voiceController!.play(); + } + } + + Stream get _positionDataStream => + Rx.combineLatest3( + cItem.voiceController!.positionStream, + cItem.voiceController!.bufferedPositionStream, + cItem.voiceController!.durationStream, + (Duration position, Duration bufferedPosition, Duration? duration) => + PositionData( + position, bufferedPosition, duration ?? Duration.zero)); + + @override + Widget build(BuildContext context) { + Size windowSize = MediaQuery.of(context).size; + screenOffset = Offset(windowSize.width / 2, windowSize.height / 2); + makeAssign(); + provider = Provider.of(context, listen: false); + return isCurrentUser ? currentUser(context) : receiptUser(context); + } + + Widget currentUser(BuildContext 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: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (userName) + .toText12( + color: MyColors.gradiantStartColor, isBold: false) + .paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + Directionality( + textDirection: provider.getTextDirection( + cItem.groupChatReplyResponse != null + ? cItem.groupChatReplyResponse!.contant + .toString() + : ""), + child: (cItem.groupChatReplyResponse != null + ? cItem.groupChatReplyResponse!.contant + .toString() + : "") + .toText10( + color: isCurrentUser + ? MyColors.grey71Color + : MyColors.white.withOpacity(0.5), + isBold: false, + maxlines: 4) + .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + ), + ], + ).expanded, + if (cItem.groupChatReplyResponse != null) + if (cItem.groupChatReplyResponse!.fileTypeId == 12 || + cItem.groupChatReplyResponse!.fileTypeId == 3 || + cItem.groupChatReplyResponse!.fileTypeId == 4) + ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: SizedBox( + height: 32, + width: 32, + child: showImage( + isReplyPreview: false, + fileName: + cItem.groupChatReplyResponse!.contant!, + fileTypeDescription: cItem + .groupChatReplyResponse! + .fileTypeResponse! + .fileTypeDescription ?? + "image/jpg")), + ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16), + ], + ), + ), + ).paddingOnly(bottom: 7).onPress(() { + // provider.scrollToMsg(cItem); + }), + if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3) + ClipRRect( + borderRadius: BorderRadius.circular(5.0), + child: SizedBox( + height: 140, + width: 227, + child: showImage( + isReplyPreview: false, + fileName: cItem.contant!, + fileTypeDescription: + cItem.fileTypeResponse!.fileTypeDescription) + .onPress(() { + showDialog( + context: context, + anchorPoint: screenOffset, + builder: (BuildContext context) => ChatImagePreviewScreen( + imgTitle: cItem.contant!, img: cItem.image!), + ); + }), + ), + ).paddingOnly(bottom: 4), + if (fileTypeID == 13 && cItem.voiceController != null) + currentWaveBubble(context, cItem) + else + Row( + children: [ + if (fileTypeID == 1 || + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + // || fileTypeID == 2 + ) + SvgPicture.asset(provider.getType(fileTypeName ?? ""), + height: 30, + width: 22, + alignment: Alignment.center, + fit: BoxFit.cover) + .paddingOnly(left: 0, right: 10), + Directionality( + textDirection: provider.getTextDirection(cItem.contant ?? ""), + child: (cItem.contant ?? "").toText12().expanded), + if (fileTypeID == 1 || + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + //|| fileTypeID == 2 + ) + const Icon(Icons.remove_red_eye, size: 16) + ], + ), + 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: 13, bottom: 5) + .objectContainerView(disablePadding: true) + .paddingOnly(left: MediaQuery.of(context).size.width * 0.3); + } + + Widget receiptUser(BuildContext context) { + return Container( + padding: const EdgeInsets.only(top: 5, left: 8, right: 13, 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: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (userName) + .toText12( + color: MyColors.gradiantStartColor, + isBold: false) + .paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + Directionality( + textDirection: provider.getTextDirection( + cItem.groupChatReplyResponse != null + ? cItem.groupChatReplyResponse!.contant + .toString() + : ""), + child: (cItem.groupChatReplyResponse != null + ? cItem.groupChatReplyResponse!.contant + .toString() + : "") + .toText10( + color: isCurrentUser + ? MyColors.grey71Color + : MyColors.white.withOpacity(0.5), + isBold: false, + maxlines: 4) + .paddingOnly( + right: 5, top: 5, bottom: 8, left: 5), + ), + ], + ).expanded, + if (cItem.groupChatReplyResponse != null) + if (cItem.groupChatReplyResponse!.fileTypeId == 12 || + cItem.groupChatReplyResponse!.fileTypeId == 3 || + cItem.groupChatReplyResponse!.fileTypeId == 4) + ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: SizedBox( + height: 32, + width: 32, + child: showImage( + isReplyPreview: true, + fileName: + cItem.groupChatReplyResponse!.contant!, + fileTypeDescription: cItem + .groupChatReplyResponse! + .fileTypeResponse! + .fileTypeDescription ?? + "image/jpg"), + ), + ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16) + ], + ), + ), + ).paddingOnly(bottom: 7).onPress(() { + // provider.scrollToMsg(cItem); + }), + if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3) + ClipRRect( + borderRadius: BorderRadius.circular(5.0), + child: SizedBox( + height: 140, + width: 227, + child: showImage( + isReplyPreview: false, + fileName: cItem.contant ?? "", + fileTypeDescription: + cItem.fileTypeResponse!.fileTypeDescription ?? + "image/jpg") + .onPress(() { + showDialog( + context: context, + anchorPoint: screenOffset, + builder: (BuildContext context) => ChatImagePreviewScreen( + imgTitle: cItem.contant ?? "", img: cItem.image!), + ); + }), + ), + ).paddingOnly(bottom: 4), + if (fileTypeID == 13 && cItem.voiceController != null) + recipetWaveBubble(context, cItem) + else + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + cItem.currentUserName!.toText10( + color: Colors.black, + ).paddingOnly(bottom: 5), + Row( + children: [ + if (fileTypeID == 1 || + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + // || fileTypeID == 2 + ) + SvgPicture.asset(provider.getType(fileTypeName ?? ""), + height: 30, + width: 22, + alignment: Alignment.center, + fit: BoxFit.cover) + .paddingOnly(left: 0, right: 10), + Directionality( + textDirection: + provider.getTextDirection(cItem.contant ?? ""), + child: (cItem.contant ?? "") + .toText12(color: Colors.white) + .expanded), + if (fileTypeID == 1 || + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + //|| fileTypeID == 2 + ) + const Icon(Icons.remove_red_eye, + color: Colors.white, size: 16) + ], + ), + Align( + alignment: Alignment.topRight, + child: dateTime.toText10( + color: Colors.white.withOpacity(.71), + ).paddingOnly(top:5), + ), + ], + ), + ])).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); + } + + Widget voiceMsg(BuildContext context) { + return Container(); + } + + Widget showImage( + {required bool isReplyPreview, + required String fileName, + required String fileTypeDescription}) { + if (cItem.isImageLoaded != null && cItem.image != null) { + return Image.memory( + cItem.image!, + height: isReplyPreview ? 32 : 140, + width: isReplyPreview ? 32 : 227, + fit: BoxFit.cover, + alignment: Alignment.center, + ); + } else { + return FutureBuilder( + future: ChatApiClient().downloadURL( + fileName: fileName, fileTypeDescription: fileTypeDescription), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState != ConnectionState.waiting) { + if (snapshot.data == null) { + return const SizedBox(); + } else { + cItem.image = snapshot.data; + cItem.isImageLoaded = true; + return Image.memory( + snapshot.data, + height: isReplyPreview ? 32 : 140, + width: isReplyPreview ? 32 : 227, + fit: BoxFit.cover, + alignment: Alignment.center, + ); + } + } else { + return SizedBox( + height: isReplyPreview ? 32 : 140, + width: isReplyPreview ? 32 : 227, + ).toShimmer(); + } + }, + ); + } + } + + Widget currentWaveBubble( + BuildContext context, GetGroupChatHistoryAsync data) { + return Container( + margin: const EdgeInsets.all(0), + 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: Row( + children: [ + //need to check and verify for group hence for now commented + // getPlayer(player: data.voiceController!, modelData: data), + StreamBuilder( + stream: _positionDataStream, + builder: + (BuildContext context, AsyncSnapshot snapshot) { + PositionData? positionData = snapshot.data; + return SeekBar( + duration: positionData?.duration ?? Duration.zero, + position: positionData?.position ?? Duration.zero, + bufferedPosition: + positionData?.bufferedPosition ?? Duration.zero, + onChangeEnd: data.voiceController!.seek, + ).expanded; + }, + ), + ], + ), + ).circle(5); + } + + Widget recipetWaveBubble( + BuildContext context, GetGroupChatHistoryAsync data) { + return Container( + margin: const EdgeInsets.all(0), + 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: Row( + mainAxisSize: MainAxisSize.max, + children: [ + //commented to verify after + //getPlayer(player: data.voiceController!, modelData: data), + StreamBuilder( + stream: _positionDataStream, + builder: + (BuildContext context, AsyncSnapshot snapshot) { + PositionData? positionData = snapshot.data; + return SeekBar( + duration: positionData?.duration ?? Duration.zero, + position: positionData?.position ?? Duration.zero, + bufferedPosition: + positionData?.bufferedPosition ?? Duration.zero, + onChangeEnd: data.voiceController!.seek, + ).expanded; + }, + ), + ], + ), + ).circle(5); + } + + Widget getPlayer( + {required AudioPlayer player, required SingleUserChatModel modelData}) { + return StreamBuilder( + stream: player.playerStateStream, + builder: (BuildContext context, AsyncSnapshot snapshot) { + PlayerState? playerState = snapshot.data; + ProcessingState? processingState = playerState?.processingState; + bool? playing = playerState?.playing; + if (processingState == ProcessingState.loading || + processingState == ProcessingState.buffering) { + return Container( + margin: const EdgeInsets.all(8.0), + width: 30.0, + height: 30.0, + child: const CircularProgressIndicator(), + ); + } else if (playing != true) { + return const Icon( + Icons.play_arrow, + size: 30, + color: MyColors.lightGreenColor, + ).onPress(() { + playVoice(context, data: modelData); + }); + } else if (processingState != ProcessingState.completed) { + return const Icon( + Icons.pause, + size: 30, + color: MyColors.lightGreenColor, + ).onPress(() { + pausePlaying(context, data: modelData); + }); + } else { + return const Icon( + Icons.replay, + size: 30, + color: MyColors.lightGreenColor, + ).onPress(() { + rePlay(context, data: modelData); + }); + } + }, + ); + } +} diff --git a/lib/ui/chat/group_chat_detaied_screen.dart b/lib/ui/chat/group_chat_detaied_screen.dart new file mode 100644 index 0000000..84ae3bd --- /dev/null +++ b/lib/ui/chat/group_chat_detaied_screen.dart @@ -0,0 +1,394 @@ +import 'dart:async'; +import 'dart:convert'; +import 'package:audio_waveforms/audio_waveforms.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/chat/call.dart'; +import 'package:mohem_flutter_app/models/chat/get_group_chat_history.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_groups_by_id.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; +import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/ui/chat/custom_auto_direction.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/chat/common.dart'; +import 'package:mohem_flutter_app/ui/chat/group_chat_bubble.dart'; +import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.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:swipe_to/swipe_to.dart'; + +class GroupChatDetailedScreenParams { + GroupResponse? groupChatDetails; + bool? isNewChat; + + GroupChatDetailedScreenParams(this.groupChatDetails, this.isNewChat); +} + +class GroupChatDetailScreen extends StatefulWidget { + const GroupChatDetailScreen({Key? key}) : super(key: key); + + @override + State createState() => _GroupChatDetailScreenState(); +} + +class _GroupChatDetailScreenState extends State { + final RefreshController _rc = RefreshController(initialRefresh: false); + late ChatProviderModel data; + late ChatCallProvider callPro; + GroupChatDetailedScreenParams? params; + + // var textDirection = TextDirection.RTL; + + void getMoreChat() async { + if (params != null) { + data.paginationVal = data.paginationVal + 10; + if (params != null) { + data.getGroupChatHistory(params!.groupChatDetails! + // senderUID: AppState().chatDetails!.response!.id!.toInt(), + // receiverUID: params!.groupChatDetails!.groupId!, + // loadMore: true, + // isNewChat: false, + ); + } + } + await Future.delayed( + const Duration(milliseconds: 1000), + ); + _rc.loadComplete(); + } + + @override + void dispose() { + data.disposeAudio(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + params = ModalRoute.of(context)!.settings.arguments as GroupChatDetailedScreenParams; + data = Provider.of(context, listen: false); + // callPro = Provider.of(context, listen: false); + if (params != null) { + data.getGroupChatHistory( + params!.groupChatDetails! + // senderUID: AppState().chatDetails!.response!.id!.toInt(), + // receiverUID: params!.groupChatHistory!.groupId!, + // loadMore: false, + // isNewChat: params!.isNewChat!, + ); + data.initAudio(receiverId: params!.groupChatDetails!.groupId!); + } + + return Scaffold( + backgroundColor: MyColors.backgroundColor, + appBar: ChatAppBarWidget( + context, + title: params!.groupChatDetails!.groupName.toString().replaceAll(".", " ").capitalizeFirstofEach, + showHomeButton: false, + // showTyping: true, + // chatUser: params!.groupChatHistory!.groupChatHistoryTargetUserList as ChatUser, + actions: [ + // SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { + // makeCall(callType: "AUDIO"); + // }), + // 24.width, + // SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() { + // makeCall(callType: "VIDEO"); + // }), + // 21.width, + ], + ), + body: SafeArea( + child: Consumer( + builder: (BuildContext context, ChatProviderModel m, Widget? child) { + return (m.isLoading + ? ChatHomeShimmer( + isDetailedScreen: true, + ) + : Column( + children: [ + 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, + itemCount: m.groupChatHistory.length, + padding: const EdgeInsets.all(21), + separatorBuilder: (BuildContext cxt, int index) => 8.height, + itemBuilder: (BuildContext context, int i) { + return SwipeTo( + iconColor: MyColors.lightGreenColor, + child: GroupChatBubble( + dateTime: m.groupChatHistory[i].createdDate!, + cItem: m.groupChatHistory[i], + ), + onRightSwipe: (val) { + m.groupChatReply( + m.groupChatHistory[i], + ); + }, + ).onPress(() async { + logger.w(m.userChatHistory[i].toJson()); + if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) { + if (m.userChatHistory[i].fileTypeId! == 1 || + m.userChatHistory[i].fileTypeId! == 5 || + m.userChatHistory[i].fileTypeId! == 7 || + m.userChatHistory[i].fileTypeId! == 6 || + m.userChatHistory[i].fileTypeId! == 8 + // || m.userChatHistory[i].fileTypeId! == 2 + ) { + m.getChatMedia(context, + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); + } + } + }); + }, + ), + ).expanded, + if (m.isReplyMsg) + 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.groupChatReplyData.first.currentUserName.toString() + ? "You" + : m.groupChatReplyData.first.currentUserName.toString().replaceAll(".", " ")) + .toText14(color: MyColors.lightGreenColor), + (m.groupChatReplyData.isNotEmpty ? m.groupChatReplyData.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) + ], + ).expanded, + 12.width, + if (m.isReplyMsg && m.groupChatReplyData.isNotEmpty) showReplyImage(m.groupChatReplyData, m), + 12.width, + const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), + ], + ), + ).expanded, + ], + ), + ), + if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") + SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), + const Divider(height: 1, color: MyColors.lightGreyEFColor), + if (m.isRecoding) + Column( + children: [ + Row( + children: [ + Text(m.buildTimer()).paddingAll(10), + if (m.isRecoding && m.isPlaying) + WaveBubble( + playerController: m.playerController, + isPlaying: m.playerController.playerState == PlayerState.playing, + onTap: () {}, + ).expanded + else + AudioWaveforms( + waveStyle: const WaveStyle( + waveColor: MyColors.lightGreenColor, + middleLineColor: Colors.transparent, + extendWaveform: true, + showBottom: true, + showTop: true, + waveThickness: 2, + showMiddleLine: false, + middleLineThickness: 0, + ), + padding: const EdgeInsets.all(5), + shouldCalculateScrolledPosition: false, + margin: EdgeInsets.zero, + size: const Size(double.infinity, 30.0), + recorderController: m.recorderController, + backgroundColor: Colors.white, + ).expanded, + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Icon( + Icons.delete_outlined, + size: 26, + color: MyColors.lightGreenColor, + ).paddingAll(10).onPress(() { + m.deleteRecoding(); + }), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) + .onPress( + () => m.sendGroupChatMessage(context, + targetUserId: params!.groupChatDetails!.groupId!, + userStatus: 0, + userEmail: "", + targetUserName: params!.groupChatDetails!.groupName!, + userList: params!.groupChatDetails!.groupUserList! + ), + ) + .paddingOnly(right: 21), + ], + ), + ], + ).objectContainerView(disablePadding: true, radius: 0), + if (!m.isRecoding) + Row( + children: [ + CustomAutoDirection( + onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL), + text: m.msgText, + child: TextField( + // textDirection: m.textDirection, + controller: m.message, + decoration: InputDecoration( + hintTextDirection: m.textDirection, + hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), + hintStyle: TextStyle(color: m.isAttachmentMsg ? 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, + ), + 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, + ), + onChanged: (String val) { + m.inputBoxDirection(val); + m.groupTypingInvoke(groupDetails: params!.groupChatDetails!, groupId: params!.groupChatDetails!.groupId!); + }, + ).expanded, + ), + if (m.sFileType.isNotEmpty) + Row( + children: [ + const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), + ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), + ], + ).onPress(() => m.removeAttachment()).paddingOnly(right: 15), + 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) + }, + ), + ).paddingOnly(right: 15), + const Icon( + Icons.mic, + color: MyColors.lightGreenColor, + ).paddingOnly(right: 15).onPress(() { + m.startRecoding(context); + }), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) + .onPress( + () =>m.sendGroupChatMessage(context, + targetUserId: params!.groupChatDetails!.groupId!, + userStatus: 0, + userEmail: "", + targetUserName: params!.groupChatDetails!.groupName!, + userList: params!.groupChatDetails!.groupUserList! + ), + ) + .paddingOnly(right: 21), + ], + ).objectContainerView(disablePadding: true, radius: 0), + ], + )); + }, + ), + ), + ); + } + + Widget showReplyImage(List data, ChatProviderModel m) { + if (data.first.isImageLoaded! && data.first.image != null) { + return Container( + width: 43, + height: 43, + decoration: BoxDecoration( + border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)), + ); + } else { + return data.first.fileTypeResponse != null && data.first.fileTypeResponse!.fileTypeName != null + ? Container( + width: 43, + height: 43, + constraints: const BoxConstraints(), + decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white), + child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName ?? ""), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) + : const SizedBox(); + } + } + + void makeCall({required String callType}) async { + callPro.initCallListeners(); + print("================== Make call Triggered ============================"); + // Map json = { + // "callerID": AppState().chatDetails!.response!.id!.toString(), + // "callerDetails": AppState().chatDetails!.toJson(), + // "receiverID": params!.chatUser!.id.toString(), + // "receiverDetails": params!.chatUser!.toJson(), + // "title": params!.chatUser!.userName!.replaceAll(".", " "), + // "calltype": callType == "VIDEO" ? "Video" : "Audio", + // }; + logger.w(json); + // CallDataModel callData = CallDataModel.fromJson(json); + // await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (BuildContext context) => OutGoingCall( + // isVideoCall: callType == "VIDEO" ? true : false, + // outGoingCallData: callData, + // ), + // ), + // ).then((value) { + // print("then"); + // callPro.stopListeners(); + // }); + } + GroupUserList getCurrentUser(int id, GroupResponse groupChatDetails) { + return groupChatDetails.groupUserList!.firstWhere((GroupUserList item) => item.id ==id); + } + +} diff --git a/lib/ui/chat/group_members.dart b/lib/ui/chat/group_members.dart new file mode 100644 index 0000000..5751101 --- /dev/null +++ b/lib/ui/chat/group_members.dart @@ -0,0 +1,131 @@ +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/app_state/app_state.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; +import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart'; +import 'package:provider/provider.dart'; +class GroupMembersScreen extends StatefulWidget { + + const GroupMembersScreen({Key? key,}) : super(key: key); + + @override + State createState() => _GroupMembersScreenState(); +} + +class _GroupMembersScreenState extends State { + late ChatProviderModel provider; + late List groupUserList; + @override + void initState() { + super.initState(); + provider = Provider.of(context, listen: false); + + } + + @override + Widget build(BuildContext context) { + groupUserList = ModalRoute.of(context)!.settings.arguments as List; + return Scaffold( + backgroundColor: MyColors.white, + appBar: ChatAppBarWidget( + context, + title: LocaleKeys.groupMembers.tr(), + showHomeButton: false, + ), + body: + groupUserList!.isNotEmpty ? ListView.separated( + itemCount: groupUserList!.length, + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.only(bottom: 5.0), + itemBuilder: (BuildContext context, int index) { + if(groupUserList![index].id != AppState().chatDetails!.response!.id) { + return SizedBox( + height: 55, + child: Row( + children: [ + + Stack( + children: [ + if (groupUserList![index].image == null) + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color:groupUserList![index].userStatus == 1 + ? MyColors.green2DColor + : Colors.red, + ), + ).circle(10), + ) + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (groupUserList![index].userName! ?? "").toText14( + color: MyColors.darkTextColor).paddingOnly( + left: 11, top: 13), + ], + ).expanded, + + + Row( + children: [ + IconButton(onPressed: (){ + goToChat(groupUserList![index]); + }, icon: Icon(Icons.chat)) + ], + ) + ], + ), + ); + } else { + return const SizedBox(); + } + }, + separatorBuilder: (BuildContext context, int index) => + const Divider(color: MyColors.lightGreyE5Color).paddingOnly( + left: 70), + ).paddingAll(10) + : Column( + children: [ + Utils + .getNoDataWidget(context) + .expanded, + ], + ) + ); + } + + void goToChat(GroupUserList groupUser){ + + ChatUser chatUser = ChatUser.fromJson(groupUser.toJson()); + Navigator.pushNamed(context, + AppRoutes.chatDetailed, + arguments: + ChatDetailedScreenParams( + chatUser, + false)); + } +} \ No newline at end of file diff --git a/lib/ui/chat/manage_group.dart b/lib/ui/chat/manage_group.dart new file mode 100644 index 0000000..7db0444 --- /dev/null +++ b/lib/ui/chat/manage_group.dart @@ -0,0 +1,142 @@ +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/app_state/app_state.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart'; +import 'package:provider/provider.dart'; + +class ManageGroupScreen extends StatefulWidget { + const ManageGroupScreen({ + Key? key, + }) : super(key: key); + + @override + State createState() => _ManageGroupScreenState(); +} + +class _ManageGroupScreenState extends State { + late ChatProviderModel provider; + GroupResponse? groupDetails; + + @override + void initState() { + super.initState(); + provider = Provider.of(context, listen: false); + } + + @override + Widget build(BuildContext context) { + groupDetails = ModalRoute.of(context)!.settings.arguments as GroupResponse; + return Scaffold( + backgroundColor: MyColors.white, + appBar: ChatAppBarWidget( + context, + title: LocaleKeys.manageGroup.tr(), + showHomeButton: false, + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + LocaleKeys.admin + .tr() + .toText14(color: MyColors.darkTextColor) + .paddingOnly(right: 25)!, + groupDetails!.groupUserList!.isNotEmpty + ? ListView.separated( + itemCount: groupDetails!.groupUserList!.length, + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.only(bottom: 5.0), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + child: Row( + children: [ + Stack( + children: [ + if (groupDetails!.groupUserList![index].image == + null) + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: groupDetails!.groupUserList![index] + .userStatus == + 1 + ? MyColors.green2DColor + : Colors.red, + ), + ).circle(10), + ) + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (groupDetails! + .groupUserList![index].userName! ?? + "") + .toText14(color: MyColors.darkTextColor) + .paddingOnly(left: 11, top: 13), + ], + ).expanded, + Row( + children: [ + Switch( + value: groupDetails! + .groupUserList![index].isAdmin!, + onChanged: groupDetails! + .groupUserList![index].id == + AppState().chatDetails!.response!.id + ? null + : (value) { + setState(() { + groupDetails!.groupUserList![index] + .isAdmin = value; + updateGroupAdmin( + groupDetails!.groupUserList!, + groupDetails!.groupId); + }); + }, + ) + ], + ) + ], + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => + const Divider(color: MyColors.lightGreyE5Color) + .paddingOnly(left: 70), + ).paddingAll(10) + : Column( + children: [ + Utils.getNoDataWidget(context).expanded, + ], + ) + ], + )); + } + + void updateGroupAdmin(List groupUserList, int? groupId) async { + //Group id need to be updated.. + provider.updateGroupAdmin(groupId, groupUserList); + } +} diff --git a/lib/ui/dialogs/id/business_card_dialog.dart b/lib/ui/dialogs/id/business_card_dialog.dart index 141abbd..ed9f260 100644 --- a/lib/ui/dialogs/id/business_card_dialog.dart +++ b/lib/ui/dialogs/id/business_card_dialog.dart @@ -1,68 +1,82 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.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'; 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'; class BusinessCardDialog extends StatelessWidget { + const BusinessCardDialog({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return RotatedBox( quarterTurns: 1, child: AspectRatio( aspectRatio: 3.5 / 2, - child: Container( - // width: MediaQuery.of(context).size.height / 2, - color: Colors.white, - margin: EdgeInsets.all(21), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Image.asset( - "assets/images/logos/bn_cloud_soloution.jpg", - width: 80, - height: 80, - ), - 12.height, - (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText20(isBold: true), - ], - ), - ), - Image.memory( - Utils.getPostBytes(AppState().memberInformationList!.businessCardQR ?? ""), - width: 100, - height: 100, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset( + "assets/images/logos/bn_cloud_soloution.jpg", + width: 94, + height: 91.15, + ).paddingOnly(top: 4), + ], ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - 1.height, - (AppState().memberInformationList!.getPositionName() ?? "").toText13(), - 12.height, - (AppState().memberInformationList!.eMPLOYEENUMBER ?? "").toText13(), - 1.height, - (AppState().memberInformationList!.eMPLOYEEEMAILADDRESS ?? "").toText13(), - 1.height, - (AppState().memberInformationList!.jOBNAME ?? "").toText13(), - ], - ), - ], - ), - ), + ), + Image.memory( + Utils.getPostBytes(AppState().memberInformationList!.businessCardQR ?? ""), + width: 129, + height: 129, + ), + ], + ).paddingOnly(top: 26, left: 8.5), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText23(isBold: true).paddingOnly(top: 15), + (AppState().memberInformationList!.getPositionName() ?? "").toText17( + color: MyColors.grey57Color, + ), + 30.height, + // (AppState().memberInformationList!.eMPLOYEENUMBER ?? "").toText13(), + Row( + children: [ + const Icon(Icons.email, size: 17.5, color: MyColors.grey3AColor).paddingOnly(right: 11.5), + ("${LocaleKeys.email.tr()}: ").toText18(color: MyColors.grey57Color), + (AppState().memberInformationList!.eMPLOYEEEMAILADDRESS ?? "").toText18(), + ], + ), + Row( + children: [ + const Icon(Icons.call, size: 17.5, color: MyColors.grey3AColor).paddingOnly(right: 11.5), + ("${LocaleKeys.mobile.tr()}: ").toText18(color: MyColors.grey57Color), + (AppState().memberInformationList!.mobileNumberWithZipCode ?? "").toText18(), + ], + ), + // 1.height, + // (AppState().memberInformationList!.jOBNAME ?? "").toText13(), + ], + ), + ], + ).paddingOnly(right: 13, left: 32, bottom: 28), ), ); } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 6f0bb98..87262e2 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -216,12 +216,12 @@ class _DashboardScreenState extends State with WidgetsBindingOb } void checkERMChannel() { - data.getITGNotification().then((MohemmItgResponseItem? val) { + data.getITGNotification().then((val) { if (val!.result!.data != null) { print("-------------------- Survey ----------------------------"); if (val.result!.data!.notificationType == "Survey") { DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (ItgMainRes? value) { + (value) { if (value!.mohemmItgResponseItem!.statusCode == 200) { if (value.mohemmItgResponseItem!.result!.data != null) { // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); @@ -237,22 +237,13 @@ class _DashboardScreenState extends State with WidgetsBindingOb } else { print("------------------------------------------- Ads --------------------"); DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (ItgMainRes? value) { + (value) { if (value!.mohemmItgResponseItem!.statusCode == 200) { if (value.mohemmItgResponseItem!.result!.data != null) { Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { "masterId": val.result!.data!.notificationMasterId, "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, }); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (BuildContext context) => ITGAdsScreen( - // addMasterId: val.result!.data!.notificationMasterId!, - // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, - // ), - // ), - // ); } } }, @@ -266,46 +257,6 @@ class _DashboardScreenState extends State with WidgetsBindingOb Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, - // appBar: AppBar( - // actions: [ - // IconButton( - // onPressed: () { - // data.getITGNotification().then((val) { - // if (val!.result!.data != null) { - // print("-------------------- Survey ----------------------------"); - // if (val.result!.data!.notificationType == "Survey") { - // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); - // } else { - // print("------------------------------------------- Ads --------------------"); - // DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - // (value) { - // if (value!.mohemmItgResponseItem!.statusCode == 200) { - // if (value.mohemmItgResponseItem!.result!.data != null) { - // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { - // "masterId": val.result!.data!.notificationMasterId, - // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, - // }); - // - // // Navigator.push( - // // context, - // // MaterialPageRoute( - // // builder: (BuildContext context) => ITGAdsScreen( - // // addMasterId: val.result!.data!.notificationMasterId!, - // // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, - // // ), - // // ), - // // ); - // } - // } - // }, - // ); - // } - // } - // }); - // }, - // icon: Icon(Icons.add)) - // ], - // ), body: Column( children: [ Row( @@ -718,7 +669,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb } else if (index == 3) { Navigator.pushNamed(context, AppRoutes.itemsForSale); } else if (index == 4) { - if (!cProvider.disableChatForThisUser) { + if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { Navigator.pushNamed(context, AppRoutes.chat); } } diff --git a/lib/ui/landing/itg/its_add_screen_video_image.dart b/lib/ui/landing/itg/its_add_screen_video_image.dart index 1e280d8..8ce89d0 100644 --- a/lib/ui/landing/itg/its_add_screen_video_image.dart +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -61,6 +61,11 @@ class _ITGAdsScreenState extends State { isVideo = true; _futureController = createVideoPlayer(rFile!); } + + advertisementData?.actionButtonsColl!.forEach((element) { + advertisementData?.actionButtonsColl!.removeWhere((element1) => element1.actionButtonId == advertisementData?.skipButtonId); + }); + setState(() {}); } @@ -152,55 +157,101 @@ class _ITGAdsScreenState extends State { textStyle: const TextStyle(color: Colors.white, fontSize: 16, letterSpacing: -0.48, fontWeight: FontWeight.bold), ), 50.height, + if (advertisementData?.isOptional ?? false) + DefaultButton(AppState().isArabic(context) ? "يتخطى" : "Skip", () async { + Navigator.pop(context); + DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Skip").then((value) { + logger.d(value); + }); + }).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8), ValueListenableBuilder( valueListenable: hasTimerEnded, builder: (context, val, child) { if (hasTimerEndedBool) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)) - .onPress(() { - try { - Navigator.pop(context); - DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Like").then((value) { - logger.d(value); - }); - } catch (ex) { - logger.wtf(ex); - Utils.handleException(ex, context, null); - } - }), - 20.width, - Container( - padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_down, color: MyColors.gradiantEndColor)) - .onPress(() { - try { - Navigator.pop(context); - DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Dislike").then((value) { - logger.d(value); - }); - } catch (ex) { - logger.wtf(ex); - Utils.handleException(ex, context, null); - } - }), - ], + return GridView.builder( + padding: EdgeInsets.zero, + itemCount: advertisementData?.actionButtonsColl!.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + String? btnText = AppState().isArabic(context) ? advertisementData?.actionButtonsColl![index].btnTextAr : advertisementData?.actionButtonsColl![index].btnTextEn; + return DefaultButton(btnText!, () async { + Navigator.pop(context); + DashboardApiClient() + .setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, advertisementData?.actionButtonsColl![index].actionValue) + .then((value) { + logger.d(value); + }); + }).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 1, + childAspectRatio: (7.0), + ), ); + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)) + // .onPress(() { + // try { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Like").then((value) { + // logger.d(value); + // }); + // } catch (ex) { + // logger.wtf(ex); + // Utils.handleException(ex, context, null); + // } + // }), + // 20.width, + // Container( + // padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_down, color: MyColors.gradiantEndColor)) + // .onPress(() { + // try { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Dislike").then((value) { + // logger.d(value); + // }); + // } catch (ex) { + // logger.wtf(ex); + // Utils.handleException(ex, context, null); + // } + // }), + // ], + // ); } else { return Container(); } }, ), 20.height, - if (advertisementData?.isOptional ?? false) - DefaultButton(AppState().isArabic(context) ? advertisementData?.skipButtonTextAr ?? "Skip" : advertisementData?.skipButtonTextEn ?? "Skip", () async { - Navigator.pop(context); - DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Skip").then((value) { - logger.d(value); - }); - }).paddingOnly(left: 100, right: 100) + // if (advertisementData?.isOptional ?? false) + // GridView.builder( + // padding: EdgeInsets.zero, + // itemCount: advertisementData?.actionButtonsColl!.length, + // shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + // itemBuilder: (context, index) { + // String? btnText = AppState().isArabic(context) ? advertisementData?.actionButtonsColl![index].btnTextAr : advertisementData?.actionButtonsColl![index].btnTextEn; + // return DefaultButton(btnText!, () async { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, advertisementData?.actionButtonsColl![index].actionValue).then((value) { + // logger.d(value); + // }); + // }).paddingAll(8); + // }, + // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + // crossAxisCount: 2, + // childAspectRatio: (4.0), + // ), + // ) + // DefaultButton(AppState().isArabic(context) ? advertisementData?.skipButtonTextAr ?? "Skip" : advertisementData?.skipButtonTextEn ?? "Skip", () async { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Skip").then((value) { + // logger.d(value); + // }); + // }).paddingOnly(left: 100, right: 100) ], ); } else { diff --git a/lib/ui/landing/widget/app_drawer.dart b/lib/ui/landing/widget/app_drawer.dart index 7df697c..4721470 100644 --- a/lib/ui/landing/widget/app_drawer.dart +++ b/lib/ui/landing/widget/app_drawer.dart @@ -119,7 +119,7 @@ class _AppDrawerState extends State { }), menuItem("assets/images/drawer/employee_id.svg", LocaleKeys.employeeDigitalID.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: EmployeeDigitialIdDialog())), if (AppState().businessCardPrivilege) - menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog())), + menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog(), isBusniessCard: true)), menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: performLogout), // menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: () {Navigator.pushNamed(context, AppRoutes.survey,); ], diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 7dabb0c..7c19b58 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -207,7 +207,7 @@ class ServicesWidget extends StatelessWidget { } else if (menuEntry.menuName == "MBL_PERINFO_SS") { Navigator.of(context).pushNamed(AppRoutes.profile); return; - } else if (menuEntry.menuName == "MY_DOCUMENTS") { + } else if (menuEntry.menuName!.isNotEmpty && menuEntry.menuName!.substring(4, menuEntry.menuName!.length) == "MBL_EMPLOYEE_DOCUMENTS") { Navigator.pushNamed(context, AppRoutes.myDocuments); return; } diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index cd3547f..611d68a 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -283,6 +283,7 @@ class _LoginScreenState extends State with WidgetsBindingObserver { try { if (!(await Utils.isGoogleServicesAvailable())) { print("HUAWEI APPPP GALLERYYYY!!!!"); + AppNotifications().init(firebaseToken, context); AppState().setIsHuawei = true; AppNotifications().initHuaweiPush(checkLoginInfo); } else { @@ -372,7 +373,18 @@ class _LoginScreenState extends State with WidgetsBindingObserver { } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, (msg) { - Utils.confirmDialog(context, msg); + Utils.confirmDialog( + context, + msg, + onTap: () async { + if (msg.toLowerCase().contains("password has expired")) { + Navigator.pop(context); + await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: username.text); + } else { + Navigator.pop(context); + } + }, + ); }); } } diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index 6dbbd18..a39b998 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -81,8 +81,8 @@ class MarathonScreen extends StatelessWidget { displayLocalizedContent( isPhoneLangArabic: AppState().isArabic(context), selectedLanguage: provider.demoMarathonDetailModel.selectedLanguage!, - arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr!, - englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!, + arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "", + englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "", ).toText22( color: MyColors.grey3AColor, isCentered: true, @@ -376,6 +376,7 @@ class MarathonScreen extends StatelessWidget { ), questionCardStatus: provider.questionCardStatus, ).paddingOnly(top: 12, left: 21, right: 21), + 50.height ], ).expanded, provider.questionCardStatus == QuestionCardStatus.winnerFound diff --git a/lib/ui/marathon/widgets/marathon_details_card.dart b/lib/ui/marathon/widgets/marathon_details_card.dart index 65d6716..2c30bfa 100644 --- a/lib/ui/marathon/widgets/marathon_details_card.dart +++ b/lib/ui/marathon/widgets/marathon_details_card.dart @@ -64,7 +64,7 @@ class MarathonDetailsCard extends StatelessWidget { marathonDetailModel.sponsors!.first.sponsorPrizes != null ? Row( children: [ - "${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true), + "${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color), Expanded( child: SizedBox( height: 30, diff --git a/lib/ui/marathon/widgets/marathon_footer.dart b/lib/ui/marathon/widgets/marathon_footer.dart index 2c82d94..a4d637f 100644 --- a/lib/ui/marathon/widgets/marathon_footer.dart +++ b/lib/ui/marathon/widgets/marathon_footer.dart @@ -1,6 +1,10 @@ +// ignore_for_file: always_specify_types + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; @@ -41,15 +45,29 @@ class MarathonFooter extends StatelessWidget { @override Widget build(BuildContext context) { - return provider.isUpComingMarathon && !provider.canPlayDemo - ? DefaultButton( + if (provider.isUpComingMarathon && !provider.canPlayDemo) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (provider.isButtonEnabled && (provider.totalSecondsToWaitForMarathon < 30 && provider.totalSecondsToWaitForMarathon > 0)) ...[ + LocaleKeys.pleaseClickButtonToJoinMarathon.tr().toText18(color: MyColors.greenColor, isCentered: true), + 20.height, + ] else if (!provider.isButtonEnabled && (provider.totalSecondsToWaitForMarathon <= 0)) ...[ + LocaleKeys.youCannotJoinTheMarathon.tr().toText18(color: MyColors.redColor, isCentered: true), + 20.height, + ], + DefaultButton( LocaleKeys.joinMarathon.tr(), provider.isButtonEnabled ? () => provider.onJoinMarathonPressed(context) : null, - ).insideContainer - : DefaultButton( - LocaleKeys.joinDemoMarathon.tr(), - () => provider.onJoinDemoMarathonPressed(context), - color: MyColors.yellowColorII, - ).insideContainer; + ) + ], + ).insideContainer; + } else { + return DefaultButton( + LocaleKeys.joinDemoMarathon.tr(), + () => provider.onJoinDemoMarathonPressed(context), + color: MyColors.yellowColorII, + ).insideContainer; + } } } diff --git a/lib/ui/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart index 6fa0ef8..ceba8be 100644 --- a/lib/ui/misc/request_submit_screen.dart +++ b/lib/ui/misc/request_submit_screen.dart @@ -32,8 +32,9 @@ class RequestSubmitScreenParams { String approvalFlag; String? selectedEmployeeID; String? popNavigateToSpecificRoute; + bool isAttachmentMandatory; - RequestSubmitScreenParams(this.title, this.transactionId, this.pItemId, this.approvalFlag, {this.selectedEmployeeID, this.popNavigateToSpecificRoute}); + RequestSubmitScreenParams(this.title, this.transactionId, this.pItemId, this.approvalFlag, {this.selectedEmployeeID, this.popNavigateToSpecificRoute, this.isAttachmentMandatory = false}); } class RequestSubmitScreen extends StatefulWidget { @@ -180,7 +181,7 @@ class _RequestSubmitScreenState extends State { physics: const BouncingScrollPhysics(), children: [ attachmentView( - LocaleKeys.attachments.tr(), + LocaleKeys.attachments.tr() + (params!.isAttachmentMandatory ? "*" : ""), ), 14.height, InputWidget( @@ -210,6 +211,11 @@ class _RequestSubmitScreenState extends State { DefaultButton( LocaleKeys.submit.tr(), () { + if (params!.isAttachmentMandatory && attachmentFiles.isEmpty) { + Utils.showToast(LocaleKeys.addAtLeastOneAttachment.tr()); + return; + } + showDialog( context: context, builder: (cxt) => ConfirmDialog( diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 0362911..20da2c8 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -9,6 +9,7 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/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/models/dyanmic_forms/get_set_values_request_model.dart'; @@ -94,17 +95,8 @@ class _DynamicInputScreenState extends State { genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); Utils.hideLoading(context); - await Navigator.pushNamed( - context, - AppRoutes.requestSubmitScreen, - arguments: RequestSubmitScreenParams( - LocaleKeys.submit.tr(), - submitEITTransactionList.pTRANSACTIONID!, - submitEITTransactionList.pITEMKEY!, - 'eit', - popNavigateToSpecificRoute: dynamicParams!.popUntilRoute, - ), - ); + await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, + arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit',isAttachmentMandatory: dynamicParams!.isAttachmentMandatory)); if (!AppState().cancelRequestTrancsection) { return; } @@ -349,10 +341,25 @@ class _DynamicInputScreenState extends State { idColName = val; if (getEitDffStructureList![j].fORMATTYPE == "X") { - idColName = Utils.formatDateDefault(idColName!); - // commenting to test - // DateTime date = DateFormat('yyyy-MM-dd').parse(idColName!); - // idColName = DateFormat('yyyy-MM-dd HH:mm:ss').format(date); + idColName = Utils.reverseFormatDate(idColName!); + if (Utils.isDate(Utils.reverseFormatDate(Utils.formatDateNew(idColName!)), "yyyy-MM-dd")) { + idColName = Utils.formatStandardDate(Utils.formatStandardDate(Utils.formatDateNew(idColName!))); + } else if (Utils.isDate(Utils.reverseFormatDate(idColName!), "dd-MM-yyyy")) { + DateTime date = DateFormat('dd-MM-yyyy').parse(idColName!); + idColName = DateFormat('yyyy-MM-dd HH:mm:ss').format(date); + } + + if (getEitDffStructureList![j].isDefaultTypeIsCDPS) { + // if (displayText.contains(" 00:00:00")) { + // displayText = displayText.replaceAll(" 00:00:00", ""); + // } + // if (displayText.contains("/")) { + // displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText)); + // } + if (idColName.contains("-")) { + idColName = idColName.parseMonth(); + } + } } } @@ -496,9 +503,20 @@ class _DynamicInputScreenState extends State { }, ).paddingOnly(bottom: 12); } else if (model.fORMATTYPE == "N") { + String displayText = model.eSERVICESDV?.pIDCOLUMNNAME ?? (getEitDffStructureList![index].fieldAnswer ?? ""); + + if (getEitDffStructureList![index].isDefaultTypeIsCDPS) { + if (displayText.contains(" 00:00:00")) { + displayText = displayText.replaceAll(" 00:00:00", ""); + } + if (displayText.contains("/")) { + displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText)); + } + } + return DynamicTextFieldWidget( (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), - model.eSERVICESDV?.pIDCOLUMNNAME ?? "", + displayText, // model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, onChange: (text) { @@ -526,9 +544,12 @@ class _DynamicInputScreenState extends State { onTap: () async { if ((getEitDffStructureList![index].eSERVICESDV?.pVALUECOLUMNNAME != null)) { if (getEitDffStructureList![index].isDefaultTypeIsCDPS) { - selectedDate = DateFormat("yyyy/MM/dd", "en_US").parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", "")); - } else { - selectedDate = DateTime.parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!); + if (displayText.contains(" 00:00:00")) { + displayText = displayText.replaceAll(" 00:00:00", ""); + } + if (displayText.contains("/")) { + displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText)); + } } } DateTime date = await _selectDate(context); diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index 9294159..94a201f 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -20,12 +20,23 @@ class DynamicListViewParams { String colsURL; bool isUpdate; String? popUntilRoute; + bool isAttachmentMandatory; List? collectionNotificationList; final String? selectedEmp; - DynamicListViewParams(this.title, this.dynamicId, - {this.selectedEmp, this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', this.isUpdate = false, this.collectionNotificationList, this.popUntilRoute}); + DynamicListViewParams( + this.title, + this.dynamicId, { + this.selectedEmp, + this.uRL = 'GET_EIT_DFF_STRUCTURE', + this.requestID = '', + this.colsURL = '', + this.isUpdate = false, + this.collectionNotificationList, + this.popUntilRoute, + this.isAttachmentMandatory = false, + }); } class DynamicListViewScreen extends StatefulWidget { diff --git a/lib/ui/screens/my_documents/my_documents_fragment.dart b/lib/ui/screens/my_documents/my_documents_fragment.dart index 89ad69d..6bc46f7 100644 --- a/lib/ui/screens/my_documents/my_documents_fragment.dart +++ b/lib/ui/screens/my_documents/my_documents_fragment.dart @@ -75,8 +75,13 @@ class _MyDocumentsFragmentState extends State { padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 11), itemBuilder: (cxt, index) { return MyDocumentItem(documentfilteredList[index], getColorByDocumentStatus(documentfilteredList[index].dOCUMENTSTATUS!)).onPress(() { - Navigator.pushNamed(context, AppRoutes.addDynamicInput, - arguments: DynamicListViewParams(documentfilteredList[index].dOCUMENTTYPE!, documentfilteredList[index].fUNCTIONNAME!, selectedEmp: AppState().getUserName, popUntilRoute: AppRoutes.myDocuments)); + if (documentfilteredList[index].eNTITLEDTOAPPLYFLAG != 'Y') return; + Navigator.pushNamed( + context, + AppRoutes.addDynamicInput, + arguments: DynamicListViewParams(documentfilteredList[index].dOCUMENTTYPE!, documentfilteredList[index].fUNCTIONNAME!, + selectedEmp: AppState().getUserName, isAttachmentMandatory: true), + ); }); }, separatorBuilder: (cxt, index) => 12.height, @@ -107,7 +112,7 @@ class _MyDocumentsFragmentState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ title.toText10(), - value.toText20(isBold: true, color: color), + value.toText18(isBold: true, color: color), ], ), ).onPress(() { @@ -120,6 +125,9 @@ class _MyDocumentsFragmentState extends State { Color getColorByDocumentStatus(String status) { Color _color; switch (status) { + case "Expired": + _color = MyColors.redA3Color; + break; case "Exist": _color = MyColors.greenColor; break; @@ -140,7 +148,7 @@ class _MyDocumentsFragmentState extends State { List list = []; switch (index) { case 1: - list = documentsList?.where((element) => element.dOCUMENTSTATUS == "Not Exist").toList() ?? []; + list = documentsList?.where((element) => element.dOCUMENTSTATUS == "Expired").toList() ?? []; break; case 2: list = documentsList?.where((element) => element.dOCUMENTSTATUS == "Missing").toList() ?? []; diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 05e542e..5d48c53 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -64,7 +64,7 @@ class _ItgDetailScreenState extends State { void getItgData() async { try { Utils.showLoading(context); - itgRequest = await WorkListApiClient().getITGFormDetails(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""); + itgRequest = await WorkListApiClient().getITGFormDetails(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""); allowedActionList = itgRequest?.allowedActions ?? []; if (allowedActionList.isNotEmpty) { isCloseAvailable = allowedActionList.any((element) => element.action == "CLOSE"); @@ -467,18 +467,18 @@ class _ItgDetailScreenState extends State { actionMode: actionMode, onTap: (note) { if (actionMode == "APPROVED") { - performApproveAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + performApproveAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); } else if (actionMode == "Answer") { - performAnswerAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + performAnswerAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); } else { - performRejectAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + performRejectAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); } }, ), ); } - void performAnswerAction(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { + void performAnswerAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); ITGRequest? itgRequest = await WorkListApiClient().answerITGRequest(requestType, taskId, itemId, employeeNumber, "", comments); @@ -502,7 +502,7 @@ class _ItgDetailScreenState extends State { } } - void performRejectAction(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { + void performRejectAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); ITGRequest? itgRequest = await WorkListApiClient().rejectITGRequest(requestType, taskId, itemId, employeeNumber, comments); @@ -526,7 +526,7 @@ class _ItgDetailScreenState extends State { } } - void performApproveAction(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { + void performApproveAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); ITGRequest? itgRequest = await WorkListApiClient().approveITGRequest(requestType, taskId, itemId, employeeNumber, comments); diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index 85395a6..2efe88b 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -211,13 +211,13 @@ class SelectedItemSheet extends StatelessWidget { try { var requestDetails = AppState().requestAllList![AppState().itgWorkListIndex!]; if (apiMode == "Delegate") { - await WorkListApiClient().delegateITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + await WorkListApiClient().delegateITGRequest(requestDetails.requestType!, requestDetails.iD, requestDetails.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", isITGRequest ? favoriteReplacements!.userName! : actionHistoryList!.uSERNAME!, comment); } else if (apiMode == "RequestInformation") { - await WorkListApiClient().informationITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + await WorkListApiClient().informationITGRequest(requestDetails.requestType!, requestDetails.iD, requestDetails.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", isITGRequest ? favoriteReplacements!.userName! : actionHistoryList!.uSERNAME!, comment); } else if (apiMode == "Answer") { - await WorkListApiClient().answerITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + await WorkListApiClient().answerITGRequest(requestDetails.requestType!, requestDetails.iD, requestDetails.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", isITGRequest ? favoriteReplacements!.userName! : actionHistoryList!.uSERNAME!, comment); } Utils.hideLoading(context); diff --git a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart index e836a07..db10717 100644 --- a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart @@ -122,13 +122,13 @@ class SelectedItgItemSheet extends StatelessWidget { var requestDetails = AppState().requestAllList![AppState().itgWorkListIndex!]; if (apiMode == "Delegate") { await WorkListApiClient() - .delegateITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); + .delegateITGRequest(requestDetails.requestType!, requestDetails.iD, requestDetails.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); } else if (apiMode == "RequestInformation") { await WorkListApiClient() - .informationITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); + .informationITGRequest(requestDetails.requestType!, requestDetails.iD, requestDetails.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); } else if (apiMode == "Answer") { await WorkListApiClient() - .answerITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); + .answerITGRequest(requestDetails.requestType!, requestDetails.iD, requestDetails.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); } Utils.hideLoading(context); Navigator.pop(context, "delegate_reload"); diff --git a/lib/ui/work_list/worklist_fragments/info_fragments.dart b/lib/ui/work_list/worklist_fragments/info_fragments.dart index d2c64f3..5edb6f1 100644 --- a/lib/ui/work_list/worklist_fragments/info_fragments.dart +++ b/lib/ui/work_list/worklist_fragments/info_fragments.dart @@ -164,7 +164,7 @@ class InfoFragment extends StatelessWidget { ), ItemDetailGrid( ItemDetailViewCol(LocaleKeys.otherCharges.tr(), poHeaderList[index].oTHERCHARGES?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.totalPOAmountWithVAT.tr(), poHeaderList[index].tOTPOAMT.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.totalPOAmountWithVAT.tr(), poHeaderList[index].lOCCURTOTPOAMT.toString() ?? ""), ), ItemDetailGrid( ItemDetailViewCol(LocaleKeys.totalPOAmountInWords.tr(), poHeaderList[index].tOTPOAMTWORD ?? ""), diff --git a/lib/widgets/dialogs/dialogs.dart b/lib/widgets/dialogs/dialogs.dart index 6765e38..a84b02a 100644 --- a/lib/widgets/dialogs/dialogs.dart +++ b/lib/widgets/dialogs/dialogs.dart @@ -1,11 +1,18 @@ import 'package:flutter/material.dart'; -void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true}) async { +void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async { return showDialog( context: context, barrierDismissible: isDismissable, builder: (context) { return Dialog( + shape: isBusniessCard + ? const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(15.0), + ), + ) + : null, backgroundColor: backgroundColor, child: child, ); diff --git a/lib/widgets/location/Location.dart b/lib/widgets/location/Location.dart index e324618..67d3cdd 100644 --- a/lib/widgets/location/Location.dart +++ b/lib/widgets/location/Location.dart @@ -47,15 +47,6 @@ class Location { Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: const Duration(seconds: 5)).then((value) { done(value); }); - // Geolocator.getLastKnownPosition(forceAndroidLocationManager: true).then((value) { - // if (value == null) { - // Geolocator.getCurrentPosition().then((value) { - // done(value); - // }); - // } else { - // done(value); - // } - // }); } else { // AppPermissions } diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index dfb4357..982e316 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -1,13 +1,11 @@ +import 'dart:async'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:huawei_location/location/fused_location_provider_client.dart'; -import 'package:huawei_location/location/location_request.dart'; -import 'package:huawei_location/location/location_settings_request.dart'; -import 'package:huawei_location/permission/permission_handler.dart'; +import 'package:huawei_location/huawei_location.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'; @@ -21,7 +19,7 @@ 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/location/Location.dart' as location; import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart'; import 'package:mohem_flutter_app/widgets/qr_scanner_dialog.dart'; import 'package:nfc_manager/nfc_manager.dart'; @@ -75,26 +73,61 @@ class _MarkAttendanceWidgetState extends State { } void checkHuaweiLocationPermission(String attendanceType) async { - PermissionHandler permissionHandler = PermissionHandler(); - - if (await permissionHandler.hasLocationPermission()) { - getHuaweiCurrentLocation(attendanceType); - } else { - bool has = await requestPermissions(); - if (has) { - getHuaweiCurrentLocation(attendanceType); + // Permission_Handler permissionHandler = PermissionHandler(); + location.Location.isEnabled((bool isEnabled) async { + if (isEnabled) { + location.Location.havePermission((bool permission) async { + if (permission) { + getHuaweiCurrentLocation(attendanceType); + } else { + bool has = await requestPermissions(); + if (has) { + getHuaweiCurrentLocation(attendanceType); + } else { + showDialog( + context: context, + builder: (BuildContext cxt) => ConfirmDialog( + message: "You need to give location permission to mark attendance", + onTap: () { + Navigator.pop(context); + }, + ), + ); + } + } + }); } else { showDialog( context: context, builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to give location permission to mark attendance", - onTap: () { + message: "You need to enable location services to mark attendance", + onTap: () async { Navigator.pop(context); + await Geolocator.openLocationSettings(); }, ), ); } - } + }); + + // if (await permissionHandler.hasLocationPermission()) { + // getHuaweiCurrentLocation(attendanceType); + // } else { + // bool has = await requestPermissions(); + // if (has) { + // getHuaweiCurrentLocation(attendanceType); + // } else { + // showDialog( + // context: context, + // builder: (BuildContext cxt) => ConfirmDialog( + // message: "You need to give location permission to mark attendance", + // onTap: () { + // Navigator.pop(context); + // }, + // ), + // ); + // } + // } } Future requestPermissions() async { @@ -134,11 +167,11 @@ class _MarkAttendanceWidgetState extends State { if (AppState().getIsHuawei) { checkHuaweiLocationPermission("NFC"); } else { - Location.isEnabled((bool isEnabled) { + location.Location.isEnabled((bool isEnabled) { if (isEnabled) { - Location.havePermission((bool permission) { + location.Location.havePermission((bool permission) { if (permission) { - Location.getCurrentLocation( + location.Location.getCurrentLocation( (Position position, bool isMocked) { if (isMocked) { markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); @@ -181,11 +214,11 @@ class _MarkAttendanceWidgetState extends State { if (AppState().getIsHuawei) { checkHuaweiLocationPermission("WIFI"); } else { - Location.isEnabled((bool isEnabled) { + location.Location.isEnabled((bool isEnabled) { if (isEnabled) { - Location.havePermission((bool permission) { + location.Location.havePermission((bool permission) { if (permission) { - Location.getCurrentLocation( + location.Location.getCurrentLocation( (Position position, bool isMocked) { if (isMocked) { markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); @@ -228,11 +261,11 @@ class _MarkAttendanceWidgetState extends State { if (AppState().getIsHuawei) { checkHuaweiLocationPermission("QR"); } else { - Location.isEnabled((bool isEnabled) { + location.Location.isEnabled((bool isEnabled) { if (isEnabled) { - Location.havePermission((bool permission) { + location.Location.havePermission((bool permission) { if (permission) { - Location.getCurrentLocation( + location.Location.getCurrentLocation( (Position position, bool isMocked) { if (isMocked) { markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); @@ -277,49 +310,70 @@ class _MarkAttendanceWidgetState extends State { ); } - void getHuaweiCurrentLocation(String attendanceType) { + void getHuaweiCurrentLocation(String attendanceType) async { try { + Utils.showLoading(context); FusedLocationProviderClient locationService = FusedLocationProviderClient(); LocationRequest locationRequest = LocationRequest(); locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; - locationRequest.interval = 1000; + locationRequest.interval = 500; List locationRequestList = [locationRequest]; LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList); - locationService.checkLocationSettings(locationSettingsRequest).then((settings) async { - await locationService.getLastLocation().then((value) { - if (value.latitude == null || value.longitude == null) { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "Unable to get your location, Please check your location settings & try again.", - onTap: () { - Navigator.pop(context); - }, - ), - ); - } else { - if (attendanceType == "QR") { - performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); - } - if (attendanceType == "WIFI") { - performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); - } - if (attendanceType == "NFC") { - performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); - } + late StreamSubscription _streamSubscription; + int requestCode = (await (locationService.requestLocationUpdates(locationRequest)))!; + + _streamSubscription = locationService.onLocationData!.listen( + (Location location) async { + Utils.hideLoading(context); + await locationService.removeLocationUpdates(requestCode); + if (attendanceType == "QR") { + performQrCodeAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); } - }).catchError((error) { - print("HUAWEI LOCATION getLastLocation ERROR!!!!!"); - print(error); - }); - }).catchError((error) { - print("HUAWEI LOCATION checkLocationSettings ERROR!!!!!"); - print(error); - if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") { - // Location service not enabled. - } - }); + if (attendanceType == "WIFI") { + performWifiAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); + } + if (attendanceType == "NFC") { + performNfcAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); + } + requestCode = 0; + }, + ); + + // locationService.checkLocationSettings(locationSettingsRequest).then((settings) async { + // await locationService.getLastLocation().then((value) { + // if (value.latitude == null || value.longitude == null) { + // showDialog( + // context: context, + // builder: (BuildContext cxt) => ConfirmDialog( + // message: "Unable to get your location, Please check your location settings & try again.", + // onTap: () { + // Navigator.pop(context); + // }, + // ), + // ); + // } else { + // if (attendanceType == "QR") { + // performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); + // } + // if (attendanceType == "WIFI") { + // performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); + // } + // if (attendanceType == "NFC") { + // performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); + // } + // } + // }).catchError((error) { + // print("HUAWEI LOCATION getLastLocation ERROR!!!!!"); + // print(error); + // }); + // }).catchError((error) { + // print("HUAWEI LOCATION checkLocationSettings ERROR!!!!!"); + // print(error); + // if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") { + // // Location service not enabled. + // } + // }); } catch (error) { print("HUAWEI LOCATION ERROR!!!!!"); print(error); diff --git a/lib/widgets/my_document_item.dart b/lib/widgets/my_document_item.dart index b0d4b51..4eb8051 100644 --- a/lib/widgets/my_document_item.dart +++ b/lib/widgets/my_document_item.dart @@ -17,7 +17,7 @@ class MyDocumentItem extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration( - color: Colors.white, + color: document.eNTITLEDTOAPPLYFLAG != 'Y' ? Colors.grey.shade300 : Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( @@ -54,18 +54,18 @@ class MyDocumentItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - document.dOCUMENTTYPE!.toText16(), + document.dOCUMENTTYPENAME!.toText16(), document.dOCUMENTSTATUS!.toText10(color: color), ], ).expanded, ], ).expanded, - if(isNotInDetailView) - const Icon( - Icons.arrow_forward, - size: 20, - color: Color(0xff2E303A), - ) + if (isNotInDetailView) + const Icon( + Icons.arrow_forward, + size: 20, + color: Color(0xff2E303A), + ) ], ).paddingOnly(top: 14, bottom: 18, right: 14, left: 24), ], diff --git a/pubspec.yaml b/pubspec.yaml index 1e61066..9f7388f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 3.2.93+300032 +#version: 3.3.01+300040 +version: 3.7.7+1 environment: sdk: ">=2.16.0 <3.0.0" @@ -54,9 +55,9 @@ dependencies: logger: ^1.1.0 flutter_countdown_timer: ^4.1.0 nfc_manager: ^3.2.0 -# uuid: ^3.0.6 -# device_info_plus: ^4.0.0 -# android_id: ^0.1.3+1 + # uuid: ^3.0.6 + # device_info_plus: ^4.0.0 + # android_id: ^0.1.3+1 platform_device_id: ^1.0.1 image_picker: ^0.8.5+3 file_picker: ^4.6.1 @@ -66,21 +67,21 @@ dependencies: open_file: ^3.2.1 wifi_iot: ^0.3.18 flutter_html: ^3.0.0-alpha.6 -# flutter_barcode_scanner: ^2.0.0 + # flutter_barcode_scanner: ^2.0.0 qr_code_scanner: ^1.0.1 -# qr_flutter: ^4.0.0 + # qr_flutter: ^4.0.0 url_launcher: ^6.0.15 share: 2.0.4 flutter_rating_bar: ^4.0.1 auto_size_text: ^3.0.0 pull_to_refresh: ^2.0.0 -# lottie json animations + # lottie json animations lottie: any -# Marathon Card Swipe + # Marathon Card Swipe appinio_swiper: ^1.1.1 expandable: ^5.0.1 -# networkImage + # networkImage cached_network_image: ^3.2.2 #Chat @@ -90,10 +91,12 @@ dependencies: #flutter_webrtc: ^0.9.34 flutter_webrtc: ^0.9.37 draggable_widget: ^2.0.0 - flutter_local_notifications: any flutter_callkit_incoming: ^2.0.0+1 + camera: ^0.10.3 + flutter_local_notifications: ^10.0.0 + #firebase_analytics: any + - #Chat Voice Message Recoding & Play audio_waveforms: ^0.1.5+1 rxdart: ^0.27.7 @@ -103,12 +106,13 @@ dependencies: video_player: ^2.5.1 just_audio: ^0.9.30 -# safe_device: ^1.1.2 + # safe_device: ^1.1.2 flutter_layout_grid: ^2.0.1 #Huawei Dependencies -# huawei_hmsavailability: ^6.6.0+300 - huawei_location: 6.0.0+302 + # huawei_hmsavailability: ^6.6.0+300 +# huawei_location: 6.0.0+302 + huawei_location: ^6.11.0+301 huawei_push: ^6.7.0+300 firebase_crashlytics: ^2.9.0 @@ -116,12 +120,12 @@ dependencies: carousel_slider: ^4.2.1 #Huawei Specified -# store_checker: ^1.1.0 + # store_checker: ^1.1.0 google_api_availability: ^3.0.1 #todo its for temporary purpose, later will remove this. dotted_border: ^2.0.0+3 - + in_app_update: 3.0.0 flutter_ios_voip_kit: ^0.1.0