diff --git a/android/app/agconnect-services.json b/android/app/agconnect-services.json new file mode 100644 index 0000000..20a7546 --- /dev/null +++ b/android/app/agconnect-services.json @@ -0,0 +1,57 @@ +{ + "agcgw_all":{ + "CN":"connect-drcn.dbankcloud.cn", + "CN_back":"connect-drcn.hispace.hicloud.com", + "DE":"connect-dre.dbankcloud.cn", + "DE_back":"connect-dre.hispace.hicloud.com", + "RU":"connect-drru.hispace.dbankcloud.ru", + "RU_back":"connect-drru.hispace.dbankcloud.cn", + "SG":"connect-dra.dbankcloud.cn", + "SG_back":"connect-dra.hispace.hicloud.com" + }, + "websocketgw_all":{ + "CN":"connect-ws-drcn.hispace.dbankcloud.cn", + "CN_back":"connect-ws-drcn.hispace.dbankcloud.com", + "DE":"connect-ws-dre.hispace.dbankcloud.cn", + "DE_back":"connect-ws-dre.hispace.dbankcloud.com", + "RU":"connect-ws-drru.hispace.dbankcloud.ru", + "RU_back":"connect-ws-drru.hispace.dbankcloud.cn", + "SG":"connect-ws-dra.hispace.dbankcloud.cn", + "SG_back":"connect-ws-dra.hispace.dbankcloud.com" + }, + "client":{ + "cp_id":"2640966000002322881", + "product_id":"737518067793559971", + "client_id":"715996003571874624", + "client_secret":"B5B89A56A53847C6BB9D216A8747E75952760DF9A8232239D8744CD847A8FFDA", + "project_id":"737518067793559971", + "app_id":"104737117", + "api_key":"DAEDACKDrYgyco9mjPV9ZUjCSh1kCr/GBV0nseHH0z2mnxlZ41RksOKmyTi+PUTwmGEPK+VxCup4F9oUf4VbDnCsjB7aNBShYcjR+g==", + "package_name":"hmg.cloudSolutions.mohem" + }, + "oauth_client":{ + "client_id":"104737117", + "client_type":1 + }, + "app_info":{ + "app_id":"104737117", + "package_name":"hmg.cloudSolutions.mohem" + }, + "configuration_version":"3.0", + "appInfos":[ + { + "package_name":"hmg.cloudSolutions.mohem", + "client":{ + "app_id":"104737117" + }, + "app_info":{ + "package_name":"hmg.cloudSolutions.mohem", + "app_id":"104737117" + }, + "oauth_client":{ + "client_type":1, + "client_id":"104737117" + } + } + ] +} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 198bc87..80eb644 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -31,6 +31,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" +apply plugin: 'com.huawei.agconnect' android { compileSdkVersion 33 @@ -58,6 +59,12 @@ android { } signingConfigs { +// debug { +// keyAlias keystoreProperties['keyAlias'] +// keyPassword keystoreProperties['keyPassword'] +// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null +// storePassword keystoreProperties['storePassword'] +// } release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] @@ -68,6 +75,9 @@ android { buildTypes { release { signingConfig signingConfigs.release + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f187ebd..5b3b2ba 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,7 +7,15 @@ - + + + + + + + + + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsForMedia + + NSAllowsArbitraryLoadsInWebContent + + CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion @@ -33,7 +42,7 @@ NFCReaderUsageDescription This App requires access to NFC to mark your attendance. NSCameraUsageDescription - This app requires camera access to capture & upload pictures. + This app requires camera access to capture & upload picture as profile image. NSFaceIDUsageDescription This app requires Face ID to allow biometric authentication for app login. NSLocationAlwaysAndWhenInUseUsageDescription @@ -46,15 +55,13 @@ This app requires photo library access to select image as document & upload it. NSMicrophoneUsageDescription This app requires microphone access to for call. - NSPhotoLibraryUsageDescription - This app requires photo library access to select image as document & upload it. UIBackgroundModes - fetch + fetch remote-notification FirebaseAppDelegateProxyEnabled - + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -80,14 +87,9 @@ ITSAppUsesNonExemptEncryption - com.apple.developer.nfc.readersession.formats TAG - com.apple.developer.nfc.readersession.felica.systemcodes - - 0000 - diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index ea7b85e..32d713c 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/request_detail_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; @@ -77,7 +76,19 @@ class AppState { bool get getIsDemoMarathon => _isDemoMarathon; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.0, mobileType: Platform.isAndroid ? "android" : "ios"); + bool _isHuawei = false; + + set setIsHuawei(bool value) => _isHuawei = value; + + bool get getIsHuawei => _isHuawei; + + String _huaweiPushToken = ""; + + set setHuaweiPushToken(String value) => _huaweiPushToken = value; + + String get getHuaweiPushToken => _huaweiPushToken; + + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.1, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; @@ -180,5 +191,4 @@ class AppState { } bool cancelRequestTrancsection = true; - } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 96fd4b0..7740624 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,12 +1,10 @@ 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://uathrmsys.moenergy.gov.sa"; //MOE UAT + // static String baseUrl = "https://hrmsys.moenergy.gov.sa"; // MOE ;LIVE + static String baseUrlServices = baseUrl + "/Services/"; // server - // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; static String erpRest = baseUrlServices + "ERP.svc/REST/"; static String swpRest = baseUrlServices + "SWP.svc/REST/"; diff --git a/lib/classes/date_uitl.dart b/lib/classes/date_uitl.dart index 3cae1cd..89e237d 100644 --- a/lib/classes/date_uitl.dart +++ b/lib/classes/date_uitl.dart @@ -60,13 +60,13 @@ class DateUtil { } } date = date + " $hours:$mins:$secs"; - DateTime returnDate = DateFormat("MM/dd/yyyy HH:mm:ss").parse(date); + DateTime returnDate = DateFormat("MM/dd/yyyy HH:mm:ss", "en_US").parse(date); return returnDate; } static DateTime convertSimpleStringDateToDateddMMyyyy(String date) { - return DateFormat("MM/dd/yyyy hh:mm:ss").parse(date); + return DateFormat("MM/dd/yyyy hh:mm:ss", "en_US").parse(date); } static DateTime convertStringToDateNoTimeZone(String date) { @@ -123,7 +123,7 @@ class DateUtil { } static String formatDateToTime(DateTime date) { - return DateFormat('hh:mm a').format(date); + return DateFormat('hh:mm a', "en_US").format(date); } static String yearMonthDay(DateTime dateTime) { @@ -419,7 +419,7 @@ class DateUtil { /// [dateTime] convert DateTime to data formatted static String getDayMonthDateFormatted(DateTime dateTime) { if (dateTime != null) - return DateFormat('dd/MM').format(dateTime); + return DateFormat('dd/MM', "en_US").format(dateTime); else return ""; } @@ -466,7 +466,7 @@ class DateUtil { /// [dateTime] convert DateTime to data formatted static String getDayMonthYearHourMinuteDateFormatted(DateTime dateTime) { if (dateTime != null) - return dateTime.day.toString() + "/" + dateTime.month.toString() + "/" + dateTime.year.toString() + " " + DateFormat('HH:mm').format(dateTime); + return dateTime.day.toString() + "/" + dateTime.month.toString() + "/" + dateTime.year.toString() + " " + DateFormat('HH:mm', "en_US").format(dateTime); else return ""; } @@ -491,11 +491,11 @@ class DateUtil { } static String getFormattedDate(DateTime dateTime, String formattedString) { - return DateFormat(formattedString).format(dateTime); + return DateFormat(formattedString, "en_US").format(dateTime); } static String convertISODateToJsonDate(String isoDate) { - return "/Date(" + DateFormat('mm-dd-yyy').parse(isoDate).millisecondsSinceEpoch.toString() + ")/"; + return "/Date(" + DateFormat('mm-dd-yyy', "en_US").parse(isoDate).millisecondsSinceEpoch.toString() + ")/"; } // static String getDay(DayOfWeek dayOfWeek) { diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 0773575..2d46642 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -1,13 +1,14 @@ -import 'dart:convert'; import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; +import 'package:huawei_push/huawei_push.dart' as huawei_push; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/main.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:firebase_core/firebase_core.dart'; final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); @@ -18,6 +19,10 @@ class AppNotifications { factory AppNotifications() => _instance; + late HmsApiAvailability hmsApiAvailability; + + String _huaweiToken = ''; + Future requestPermissions() async { if (Platform.isIOS) { await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); @@ -35,6 +40,7 @@ class AppNotifications { } void init(String? firebaseToken) async { + hmsApiAvailability = HmsApiAvailability(); await requestPermissions(); AppState().setDeviceToken = firebaseToken; await Permission.notification.isDenied.then((bool value) { @@ -57,6 +63,48 @@ class AppNotifications { FirebaseMessaging.instance.onTokenRefresh.listen((String token) { AppState().setDeviceToken = token; }); + + if (Platform.isAndroid) { + await hmsApiAvailability.isHMSAvailable().then((value) async { + if (value == 0) { + huawei_push.Push.enableLogger(); + var result = await huawei_push.Push.setAutoInitEnabled(true); + + huawei_push.Push.onNotificationOpenedApp.listen((message) { + // newMessage(toFirebaseRemoteMessage(message)); + }, onError: (e) => print(e.toString())); + + huawei_push.Push.onMessageReceivedStream.listen((message) { + // newMessage(toFirebaseRemoteMessage(message)); + }, onError: (e) => print(e.toString())); + } + }).catchError((err) { + print(err); + }); + } + } + + void initHuaweiPush(Function loginCallback) { + AppState().setIsHuawei = true; + initTokenStream(loginCallback); + huawei_push.Push.getToken(""); + } + + // HUAWEI PUSH TOKEN IMPLEMENTATION + void _onTokenEvent(String event) { + _huaweiToken = event; + AppState().setHuaweiPushToken = _huaweiToken; + debugPrint("HUAWEI PUSH TOKEN: $_huaweiToken"); + } + + void _onTokenError(Object error) {} + + Future initTokenStream(Function loginCallback) async { + huawei_push.Push.getTokenStream.listen(_onTokenEvent, onError: _onTokenError).onData((data) { + AppState().setHuaweiPushToken = data; + debugPrint("HUAWEI PUSH TOKEN: $data"); + loginCallback(); + }); } void _handleMessage(RemoteMessage message) { diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 2c36694..8822123 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -98,7 +98,8 @@ class Utils { static void handleException(dynamic exception, cxt, Function(String)? onErrorMessage) { String errorMessage; - if (exception.error.errorType != null && exception.error.errorType == 4) { + print("exception:$exception"); + if (exception?.error?.errorType != null && exception.error.errorType == 4) { Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.appUpdateScreen, (_) => false, arguments: exception.error?.errorMessage); } else { if (exception is APIException) { @@ -266,7 +267,7 @@ class Utils { static String getMonthNamedFormat(DateTime date) { /// it will return like "29-Sep-2022" - return DateFormat('dd-MMM-yyyy').format(date); + return DateFormat('dd-MMM-yyyy', "en_US").format(date); } static String reverseFormatDate(String date) { @@ -336,9 +337,9 @@ class Utils { return date; } else { if (date.toLowerCase().split("-")[1].length == 3) { - return DateFormat('dd-MM-yyyy').format(DateFormat('dd-MMM-yyyy').parseLoose(date)); + return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('dd-MMM-yyyy', "en_US").parseLoose(date)); } else { - return DateFormat('dd-MM-yyyy').format(DateFormat('yyyy-MM-dd').parseLoose(date)); + return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('yyyy-MM-dd', "en_US").parseLoose(date)); } // return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date)); } diff --git a/lib/config/app_feature_config.dart b/lib/config/app_feature_config.dart new file mode 100644 index 0000000..058d971 --- /dev/null +++ b/lib/config/app_feature_config.dart @@ -0,0 +1 @@ +var json = {}; diff --git a/lib/config/env.dart b/lib/config/env.dart index b78c5e4..38fa108 100644 --- a/lib/config/env.dart +++ b/lib/config/env.dart @@ -1,9 +1,8 @@ // ignore_for_file: prefer_single_quotes, lines_longer_than_80_chars final -Map env = { - "appConfig": "lib/config/config_en.json", - - // Worklist (Dynamic ListView, Dynamic Forms, Dynamic Submission) +// link to generate dart class https://www.webinovers.com/web-tools/json-to-dart-convertor +Map _env = { + "appConfig": "lib/config/config_en.json", "login": { "verification": true, "verificationMethod": { @@ -21,6 +20,7 @@ Map env = { "monthlyAttendance": false, "vocationRules": false, }, + "itg": false, "marathon": false, "offersDiscount": false, "myTeams": false, @@ -32,4 +32,175 @@ Map env = { "chat": false, "monthlyAttendance": false, "vocationRules": false, + "canEdit": false, }; + +Env env = Env.fromJson(_env); + +class Env { + Env({ + required this.appConfig, + required this.login, + required this.bottomBar, + required this.dashboard, + required this.itg, + required this.marathon, + required this.offersDiscount, + required this.myTeams, + required this.modifiy, + required this.myRequest, + required this.pendingTransactions, + required this.myProfile, + required this.itemsForSale, + required this.chat, + required this.monthlyAttendance, + required this.vocationRules, + required this.canEdit, + }); + + late final String appConfig; + late final Login login; + late final bool bottomBar; + late final Dashboard dashboard; + late final bool itg; + late final bool marathon; + late final bool offersDiscount; + late final bool myTeams; + late final bool modifiy; + late final bool myRequest; + late final bool pendingTransactions; + late final bool myProfile; + late final bool itemsForSale; + late final bool chat; + late final bool monthlyAttendance; + late final bool vocationRules; + late final bool canEdit; + + Env.fromJson(Map json) { + appConfig = json['appConfig']; + login = Login.fromJson(json['login']); + bottomBar = json['bottomBar']; + dashboard = Dashboard.fromJson(json['dashboard']); + marathon = json['marathon']; + itg = json['itg']; + offersDiscount = json['offersDiscount']; + myTeams = json['myTeams']; + modifiy = json['modifiy']; + myRequest = json['myRequest']; + pendingTransactions = json['pendingTransactions']; + myProfile = json['myProfile']; + itemsForSale = json['itemsForSale']; + chat = json['chat']; + monthlyAttendance = json['monthlyAttendance']; + vocationRules = json['vocationRules']; + canEdit = json['canEdit']; + } + + Map toJson() { + var _data = {}; + _data['appConfig'] = appConfig; + _data['login'] = login.toJson(); + _data['bottomBar'] = bottomBar; + _data['dashboard'] = dashboard.toJson(); + _data['marathon'] = marathon; + _data['itg'] = itg; + _data['offersDiscount'] = offersDiscount; + _data['myTeams'] = myTeams; + _data['modifiy'] = modifiy; + _data['myRequest'] = myRequest; + _data['pendingTransactions'] = pendingTransactions; + _data['myProfile'] = myProfile; + _data['itemsForSale'] = itemsForSale; + _data['chat'] = chat; + _data['monthlyAttendance'] = monthlyAttendance; + _data['vocationRules'] = vocationRules; + _data['canEdit'] = canEdit; + return _data; + } +} + +class Login { + Login({ + required this.verification, + required this.verificationMethod, + required this.forgetPassword, + }); + + late final bool verification; + late final VerificationMethod verificationMethod; + late final bool forgetPassword; + + Login.fromJson(Map json) { + verification = json['verification']; + verificationMethod = VerificationMethod.fromJson(json['verificationMethod']); + forgetPassword = json['forgetPassword']; + } + + Map toJson() { + var _data = {}; + _data['verification'] = verification; + _data['verificationMethod'] = verificationMethod.toJson(); + _data['forgetPassword'] = forgetPassword; + return _data; + } +} + +class VerificationMethod { + VerificationMethod({ + required this.whatsapp, + }); + + late final bool whatsapp; + + VerificationMethod.fromJson(Map json) { + whatsapp = json['whatsapp']; + } + + Map toJson() { + var _data = {}; + _data['whatsapp'] = whatsapp; + return _data; + } +} + +class Dashboard { + Dashboard({ + required this.attendance, + required this.worklist, + required this.ticketBalance, + required this.leaveBalance, + required this.missingSwipe, + required this.monthlyAttendance, + required this.vocationRules, + }); + + late final bool attendance; + late final bool worklist; + late final bool ticketBalance; + late final bool leaveBalance; + late final bool missingSwipe; + late final bool monthlyAttendance; + late final bool vocationRules; + + Dashboard.fromJson(Map json) { + attendance = json['attendance']; + worklist = json['worklist']; + ticketBalance = json['ticketBalance']; + leaveBalance = json['leaveBalance']; + missingSwipe = json['missingSwipe']; + monthlyAttendance = json['monthlyAttendance']; + vocationRules = json['vocationRules']; + } + + Map toJson() { + var _data = {}; + _data['attendance'] = attendance; + _data['worklist'] = worklist; + _data['ticketBalance'] = ticketBalance; + _data['leaveBalance'] = leaveBalance; + _data['missingSwipe'] = missingSwipe; + _data['monthlyAttendance'] = monthlyAttendance; + _data['vocationRules'] = vocationRules; + return _data; + } +} diff --git a/lib/dialogs/otp_dialog.dart b/lib/dialogs/otp_dialog.dart index 9158b94..9f7c82e 100644 --- a/lib/dialogs/otp_dialog.dart +++ b/lib/dialogs/otp_dialog.dart @@ -9,7 +9,6 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/otp_widget.dart'; -import 'package:sizer/sizer.dart'; final ValueNotifier otpFieldClear = ValueNotifier(""); diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 53b70a5..54ffe20 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -221,7 +221,7 @@ extension EmailValidator on String { String date = this.split("T")[0]; String time = this.split("T")[1]; var dates = date.split("-"); - return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a').format(DateFormat('hh:mm:ss').parse(time))}"; + return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a', "en_US").format(DateFormat('hh:mm:ss', "en_US").parse(time))}"; } String getMonth(int month) { diff --git a/lib/main.dart b/lib/main.dart index d7b9646..b00609b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,9 +6,11 @@ import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:mohem_flutter_app/config/env.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'; @@ -25,7 +27,6 @@ Logger logger = Logger( ), ); - class MyHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { @@ -62,12 +63,17 @@ Future main() async { ChangeNotifierProvider( create: (_) => EITProviderModel(), ), - ChangeNotifierProvider( - create: (_) => ChatProviderModel(), - ), - ChangeNotifierProvider( - create: (_) => MarathonProvider(), - ) + if (env.chat) + ChangeNotifierProvider( + create: (_) => ChatProviderModel(), + ), + if (env.marathon) + ChangeNotifierProvider( + create: (_) => MarathonProvider(), + ), + // ChangeNotifierProvider( + // create: (_) => ChatCallProvider(), + // ), ], child: const MyApp(), ), @@ -259,5 +265,3 @@ class MyApp extends StatelessWidget { // }); // } // } - - diff --git a/lib/models/chat/call.dart b/lib/models/chat/call.dart index 7f8f6eb..ce58ae3 100644 --- a/lib/models/chat/call.dart +++ b/lib/models/chat/call.dart @@ -7,127 +7,191 @@ import 'dart:convert'; class CallDataModel { CallDataModel({ this.callerId, - this.callReceiverID, - this.notificationForeground, - this.message, + this.callerDetails, + this.receiverId, + this.receiverDetails, this.title, - this.type, - this.identity, - this.name, - this.isCall, - this.isWebrtc, - this.contant, - this.contantNo, - this.chatEventId, - this.fileTypeId, - this.currentUserId, - this.chatSource, - this.userChatHistoryLineRequestList, - this.server, + this.calltype, }); String? callerId; - String? callReceiverID; - String? notificationForeground; - String? message; - String? title; - String? type; - String? identity; - String? name; - String? isCall; - String? isWebrtc; - String? contant; - String? contantNo; - String? chatEventId; - dynamic? fileTypeId; - String? currentUserId; - String? chatSource; - List? userChatHistoryLineRequestList; - String? server; + CallerDetails? callerDetails; + String? receiverId; + ReceiverDetails? receiverDetails; + dynamic title; + String? calltype; factory CallDataModel.fromRawJson(String str) => CallDataModel.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); factory CallDataModel.fromJson(Map json) => CallDataModel( - callerId: json["callerID"] == null ? null : json["callerID"], - callReceiverID: json["callReceiverID"] == null ? null : json["callReceiverID"], - notificationForeground: json["notification_foreground"] == null ? null : json["notification_foreground"], - message: json["message"] == null ? null : json["message"], - title: json["title"] == null ? null : json["title"], - type: json["type"] == null ? null : json["type"], - identity: json["identity"] == null ? null : json["identity"], - name: json["name"] == null ? null : json["name"], - isCall: json["is_call"] == null ? null : json["is_call"], - isWebrtc: json["is_webrtc"] == null ? null : json["is_webrtc"], - contant: json["contant"] == null ? null : json["contant"], - contantNo: json["contantNo"] == null ? null : json["contantNo"], - chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], - fileTypeId: json["fileTypeId"], - currentUserId: json["currentUserId"] == null ? null : json["currentUserId"], - chatSource: json["chatSource"] == null ? null : json["chatSource"], - userChatHistoryLineRequestList: json["userChatHistoryLineRequestList"] == null - ? null - : List.from( - json["userChatHistoryLineRequestList"].map( - (x) => UserChatHistoryLineRequestList.fromJson(x), - ), - ), - server: json["server"] == null ? null : json["server"], - ); + callerId: json["callerID"], + callerDetails: json["callerDetails"] == null ? null : CallerDetails.fromJson(json["callerDetails"]), + receiverId: json["receiverID"], + receiverDetails: json["receiverDetails"] == null ? null : ReceiverDetails.fromJson(json["receiverDetails"]), + title: json["title"], + calltype: json["calltype"], + ); + + Map toJson() => { + "callerID": callerId, + "callerDetails": callerDetails?.toJson(), + "receiverID": receiverId, + "receiverDetails": receiverDetails?.toJson(), + "title": title, + "calltype": calltype, + }; +} + +class CallerDetails { + CallerDetails({ + this.response, + this.errorResponses, + }); + + Response? response; + dynamic errorResponses; + + factory CallerDetails.fromRawJson(String str) => CallerDetails.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory CallerDetails.fromJson(Map json) => CallerDetails( + response: json["response"] == null ? null : Response.fromJson(json["response"]), + errorResponses: json["errorResponses"], + ); Map toJson() => { - "callerID": callerId == null ? null : callerId, - "callReceiverID": callReceiverID == null ? null : callReceiverID, - "notification_foreground": notificationForeground == null ? null : notificationForeground, - "message": message == null ? null : message, - "title": title == null ? null : title, - "type": type == null ? null : type, - "identity": identity == null ? null : identity, - "name": name == null ? null : name, - "is_call": isCall == null ? null : isCall, - "is_webrtc": isWebrtc == null ? null : isWebrtc, - "contant": contant == null ? null : contant, - "contantNo": contantNo == null ? null : contantNo, - "chatEventId": chatEventId == null ? null : chatEventId, - "fileTypeId": fileTypeId, - "currentUserId": currentUserId == null ? null : currentUserId, - "chatSource": chatSource == null ? null : chatSource, - "userChatHistoryLineRequestList": userChatHistoryLineRequestList == null - ? null - : List.from( - userChatHistoryLineRequestList!.map( - (x) => x.toJson(), - ), - ), - "server": server == null ? null : server, - }; + "response": response?.toJson(), + "errorResponses": errorResponses, + }; } -class UserChatHistoryLineRequestList { - UserChatHistoryLineRequestList({ - this.isSeen, - this.isDelivered, - this.targetUserId, - this.targetUserStatus, +class Response { + Response({ + this.id, + this.userName, + this.email, + this.phone, + this.title, + this.token, + this.isDomainUser, + this.isActiveCode, + this.encryptedUserId, + this.encryptedUserName, }); - bool? isSeen; - bool? isDelivered; - int? targetUserId; - int? targetUserStatus; + int? id; + String? userName; + String? email; + dynamic phone; + String? title; + String? token; + bool? isDomainUser; + bool? isActiveCode; + String? encryptedUserId; + String? encryptedUserName; + + factory Response.fromRawJson(String str) => Response.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Response.fromJson(Map json) => Response( + id: json["id"], + userName: json["userName"], + email: json["email"], + phone: json["phone"], + title: json["title"], + token: json["token"], + isDomainUser: json["isDomainUser"], + isActiveCode: json["isActiveCode"], + encryptedUserId: json["encryptedUserId"], + encryptedUserName: json["encryptedUserName"], + ); + + Map toJson() => { + "id": id, + "userName": userName, + "email": email, + "phone": phone, + "title": title, + "token": token, + "isDomainUser": isDomainUser, + "isActiveCode": isActiveCode, + "encryptedUserId": encryptedUserId, + "encryptedUserName": encryptedUserName, + }; +} + +class ReceiverDetails { + ReceiverDetails({ + 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, + }); + + int? id; + String? userName; + String? email; + dynamic phone; + dynamic title; + int? userStatus; + String? image; + int? unreadMessageCount; + dynamic userAction; + bool? isPin; + bool? isFav; + bool? isAdmin; + String? rKey; + int? totalCount; + + factory ReceiverDetails.fromRawJson(String str) => ReceiverDetails.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); - factory UserChatHistoryLineRequestList.fromJson(Map json) => UserChatHistoryLineRequestList( - isSeen: json["isSeen"] == null ? null : json["isSeen"], - isDelivered: json["isDelivered"] == null ? null : json["isDelivered"], - targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], - targetUserStatus: json["targetUserStatus"] == null ? null : json["targetUserStatus"], - ); + factory ReceiverDetails.fromJson(Map json) => ReceiverDetails( + 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() => { - "isSeen": isSeen == null ? null : isSeen, - "isDelivered": isDelivered == null ? null : isDelivered, - "targetUserId": targetUserId == null ? null : targetUserId, - "targetUserStatus": targetUserStatus == null ? null : targetUserStatus, - }; + "id": id, + "userName": userName, + "email": email, + "phone": phone, + "title": title, + "userStatus": userStatus, + "image": image, + "unreadMessageCount": unreadMessageCount, + "userAction": userAction, + "isPin": isPin, + "isFav": isFav, + "isAdmin": isAdmin, + "rKey": rKey, + "totalCount": totalCount, + }; } diff --git a/lib/models/get_eit_dff_structure_list_model.dart b/lib/models/get_eit_dff_structure_list_model.dart index 3aed98c..c659cc2 100644 --- a/lib/models/get_eit_dff_structure_list_model.dart +++ b/lib/models/get_eit_dff_structure_list_model.dart @@ -31,6 +31,7 @@ class GetEITDFFStructureList { List? pARENTSEGMENTSVSSplitedVS; String? rEADONLY; String? rEQUIREDFLAG; + String? rEQCOLTIP; String? sEGMENTNAME; String? sEGMENTPROMPT; int? sEGMENTSEQNUM; @@ -73,6 +74,7 @@ class GetEITDFFStructureList { this.pARENTSEGMENTSVSSplitedVS, this.rEADONLY, this.rEQUIREDFLAG, + this.rEQCOLTIP, this.sEGMENTNAME, this.sEGMENTPROMPT, this.sEGMENTSEQNUM, @@ -132,7 +134,6 @@ class GetEITDFFStructureList { }); } pARENTSEGMENTSVS = json['PARENT_SEGMENTS_VS']; - if (json['PARENT_SEGMENTS_VS_SplitedVS'] != null) { pARENTSEGMENTSVSSplitedVS = []; json['PARENT_SEGMENTS_VS_SplitedVS'].forEach((v) { @@ -141,6 +142,7 @@ class GetEITDFFStructureList { } rEADONLY = json['READ_ONLY']; rEQUIREDFLAG = json['REQUIRED_FLAG']; + rEQCOLTIP = json['REQ_COL_TIP']; sEGMENTNAME = json['SEGMENT_NAME']; sEGMENTPROMPT = json['SEGMENT_PROMPT']; sEGMENTSEQNUM = json['SEGMENT_SEQ_NUM']; @@ -171,9 +173,6 @@ class GetEITDFFStructureList { if (this.eSERVICESVS != null) { data['E_SERVICES_VS'] = this.eSERVICESVS!.map((v) => v.toJson()).toList(); } - // if (this.eSERVICESVS != null) { - // data['E_SERVICES_VS'] = this.eSERVICESVS!.toList(); - // } data['FLEX_VALUE_SET_NAME'] = this.fLEXVALUESETNAME; data['FORMAT_TYPE'] = this.fORMATTYPE; data['FORMAT_TYPE_DSP'] = this.fORMATTYPEDSP; @@ -193,9 +192,9 @@ class GetEITDFFStructureList { if (this.pARENTSEGMENTSVSSplitedVS != null) { data['PARENT_SEGMENTS_VS_SplitedVS'] = this.pARENTSEGMENTSVSSplitedVS!.map((v) => v.toJson()).toList(); } - data['READ_ONLY'] = this.rEADONLY; data['REQUIRED_FLAG'] = this.rEQUIREDFLAG; + data['REQ_COL_TIP'] = this.rEQCOLTIP; data['SEGMENT_NAME'] = this.sEGMENTNAME; data['SEGMENT_PROMPT'] = this.sEGMENTPROMPT; data['SEGMENT_SEQ_NUM'] = this.sEGMENTSEQNUM; diff --git a/lib/models/get_mobile_login_info_list_model.dart b/lib/models/get_mobile_login_info_list_model.dart index a2f7799..d544ef5 100644 --- a/lib/models/get_mobile_login_info_list_model.dart +++ b/lib/models/get_mobile_login_info_list_model.dart @@ -1,6 +1,6 @@ class GetMobileLoginInfoListModel { int? iD; - int? employeeID; + String? employeeID; int? channelID; int? companyID; String? deviceType; diff --git a/lib/provider/chat_call_provider.dart b/lib/provider/chat_call_provider.dart new file mode 100644 index 0000000..45205df --- /dev/null +++ b/lib/provider/chat_call_provider.dart @@ -0,0 +1,187 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart'; +import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; + +class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { + ///////////////////// Web RTC Video Calling ////////////////////// + // Video Call + late RTCPeerConnection _peerConnection; + RTCVideoRenderer _localVideoRenderer = RTCVideoRenderer(); + final RTCVideoRenderer _remoteRenderer = RTCVideoRenderer(); + + MediaStream? _localStream; + MediaStream? _remoteStream; + + void initCallListeners() { + chatHubConnection.on("OnCallAcceptedAsync", onCallAcceptedAsync); + chatHubConnection.on("OnIceCandidateAsync", onIceCandidateAsync); + chatHubConnection.on("OnOfferAsync", onOfferAsync); + chatHubConnection.on("OnAnswerOffer", onAnswerOffer); + chatHubConnection.on("OnHangUpAsync", onHangUpAsync); + chatHubConnection.on("OnCallDeclinedAsync", onCallDeclinedAsync); + } + + //Video Constraints + var videoConstraints = { + "video": { + "mandatory": { + "width": {"min": 320}, + "height": {"min": 180} + }, + "optional": [ + { + "width": {"max": 1280} + }, + {"frameRate": 25}, + {"facingMode": "user"} + ] + }, + "frameRate": 25, + "width": 420, //420,//640,//1280, + "height": 240 //240//480//720 + }; + + // Audio Constraints + var audioConstraints = { + "sampleRate": 8000, + "sampleSize": 16, + "channelCount": 2, + "echoCancellation": true, + "audio": true, + }; + + Future _createPeerConnection() async { + // {"url": "stun:stun.l.google.com:19302"}, + Map configuration = { + "iceServers": [ + {"urls": 'stun:15.185.116.59:3478'}, + {"urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin"} + ] + }; + + Map offerSdpConstraints = { + "mandatory": { + "OfferToReceiveAudio": true, + "OfferToReceiveVideo": true, + }, + "optional": [], + }; + + RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints); + // if (pc != null) print(pc); + //pc.addStream(widget.localStream); + + pc.onIceCandidate = (e) { + if (e.candidate != null) { + print(json.encode({ + 'candidate': e.candidate.toString(), + 'sdpMid': e.sdpMid.toString(), + 'sdpMlineIndex': e.sdpMLineIndex, + })); + } + }; + pc.onIceConnectionState = (e) { + print(e); + }; + pc.onAddStream = (stream) { + print('addStream: ' + stream.id); + _remoteRenderer.srcObject = stream; + }; + return pc; + } + + void init() { + initRenderers(); + _createPeerConnection().then((pc) { + _peerConnection = pc; + // _setRemoteDescription(widget.info); + }); + } + + void initRenderers() { + _localVideoRenderer.initialize(); + _remoteRenderer.initialize(); + initLocalCamera(); + } + + void initLocalCamera() async { + _localStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true}); + _localVideoRenderer.srcObject = _localStream; + // _localVideoRenderer.srcObject = await navigator.mediaDevices + // .getUserMedia({'video': true, 'audio': true}); + print('this source Object'); + print('this suarce ${_localVideoRenderer.srcObject != null}'); + notifyListeners(); + } + + void startCall({required String callType}) {} + + void endCall() {} + + void checkCall(Map message) { + switch (message["callStatus"]) { + case 'connected': + {} + break; + case 'offer': + {} + break; + case 'accept': + {} + break; + case 'candidate': + {} + break; + case 'bye': + {} + break; + case 'leave': + {} + break; + } + } + + //// Listeners Methods //// + + void onCallAcceptedAsync(List? params) {} + + void onIceCandidateAsync(List? params) {} + + void onOfferAsync(List? params) {} + + void onAnswerOffer(List? params) {} + + void onHangUpAsync(List? params) {} + + void onCallDeclinedAsync(List? params) {} + + //// Invoke Methods + + Future invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async { + List args = []; + if (invokeMethod == "answerCallAsync") { + args = [currentUserID, targetUserID]; + } else if (invokeMethod == "CallUserAsync") { + args = [currentUserID, targetUserID, isVideoCall]; + } else if (invokeMethod == "IceCandidateAsync") { + args = [targetUserID, data]; + } else if (invokeMethod == "OfferAsync") { + args = [targetUserID, data]; + } else if (invokeMethod == "AnswerOfferAsync") { + args = [targetUserID, data]; + //json In Data + } + await chatHubConnection.invoke(invokeMethod, args: args); + } + + void stopListeners() async { + chatHubConnection.off('OnCallDeclinedAsync'); + chatHubConnection.off('OnCallAcceptedAsync'); + chatHubConnection.off('OnIceCandidateAsync'); + chatHubConnection.off('OnAnswerOffer'); + } +} diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 56001d6..d374114 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -69,6 +69,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List teamMembersList = []; Material.TextDirection textDirection = Material.TextDirection.ltr; + bool isRTL = false; + String msgText = ""; //Chat Home Page Counter int chatUConvCounter = 0; @@ -77,6 +79,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? chatUsersList = []; int pageNo = 1; + bool disbaleChatForThisUser = false; + Future getUserAutoLoginToken() async { userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); if (userLoginResponse.response != null) { @@ -86,6 +90,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Utils.showToast( userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", ); + disbaleChatForThisUser = true; + notifyListeners(); } } @@ -117,6 +123,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + if (kDebugMode) { logger.i("All listeners registered"); } @@ -912,7 +919,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } String dateFormte(DateTime data) { - DateFormat f = DateFormat('hh:mm a dd MMM yyyy'); + DateFormat f = DateFormat('hh:mm a dd MMM yyyy', "en_US"); f.format(data); return f.format(data); } @@ -1007,23 +1014,25 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void disposeData() { - search.clear(); - isChatScreenActive = false; - receiverID = 0; - paginationVal = 0; - message.text = ''; - isTextMsg = false; - isAttachmentMsg = false; - isVoiceMsg = false; - isReplyMsg = false; - repliedMsg = []; - sFileType = ""; - deleteData(); - favUsersList.clear(); - searchedChats?.clear(); - pChatHistory?.clear(); - chatHubConnection.stop(); - AppState().chatDetails = null; + if (!disbaleChatForThisUser) { + search.clear(); + isChatScreenActive = false; + receiverID = 0; + paginationVal = 0; + message.text = ''; + isTextMsg = false; + isAttachmentMsg = false; + isVoiceMsg = false; + isReplyMsg = false; + repliedMsg = []; + sFileType = ""; + deleteData(); + favUsersList.clear(); + searchedChats?.clear(); + pChatHistory?.clear(); + chatHubConnection.stop(); + AppState().chatDetails = null; + } } void deleteData() { @@ -1407,17 +1416,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void inputBoxDirection(String val) { if (val.isNotEmpty) { isTextMsg = true; - RegExp exp = RegExp("[a-zA-Z]"); - if (exp.hasMatch(val.substring(val.length - 1)) && val.substring(val.length - 1) != " ") { - textDirection = Material.TextDirection.ltr; - notifyListeners(); - } else if (val.substring(val.length - 1) != " " && !exp.hasMatch(val.substring(val.length - 1))) { - textDirection = Material.TextDirection.rtl; - notifyListeners(); - } } else { isTextMsg = false; } + msgText = val; + notifyListeners(); + } + + void onDirectionChange(bool val) { + isRTL = val; + notifyListeners(); } Material.TextDirection getTextDirection(String v) { @@ -1451,18 +1459,19 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void openChatByNoti(BuildContext context) async { + SingleUserChatModel nUser = SingleUserChatModel(); Utils.saveStringFromPrefs("isAppOpendByChat", "false"); - SingleUserChatModel nUser = SingleUserChatModel.fromJson(jsonDecode(await Utils.getStringFromPrefs("notificationData"))); - Utils.saveStringFromPrefs("notificationData", "null"); - logger.w(jsonEncode(nUser)); - 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; - } else { - openChatByNoti(context); + 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"); } } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 1ca89ec..3476729 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -103,11 +103,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { drawerMenuItemList = [ DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile), - DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation), - DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi), - DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), - // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), - DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword), + // DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation), + // DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi), + // DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), + // // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), + // DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword), + // ]; notifyListeners(); @@ -139,15 +140,17 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { getOpenNotificationsList = genericResponseModel?.getOpenNotificationsList; workListCounter = genericResponseModel?.pOPENNTFNUMBER ?? 0; - - itgFormsModel = await DashboardApiClient().getItgFormsPendingTask(); + if (env.itg) itgFormsModel = await DashboardApiClient().getItgFormsPendingTask(); workListCounter = workListCounter + (itgFormsModel?.totalCount ?? 0); - GenericResponseModel? cocGenericResponseModel = await DashboardApiClient().getCOCNotifications(); - cocCount = cocGenericResponseModel?.mohemmITGPendingTaskResponseItem; - if (cocCount != null) { - cocFinalCount = (cocCount?.escalation ?? 0) + (cocCount?.waitingToClose ?? 0) + (cocCount?.waitingForAcceptance ?? 0) + (cocCount?.extendTATRequest ?? 0); - workListCounter += cocFinalCount; + if (env.itg) { + GenericResponseModel? cocGenericResponseModel = await DashboardApiClient().getCOCNotifications(); + cocCount = cocGenericResponseModel?.mohemmITGPendingTaskResponseItem; + if (cocCount != null) { + cocFinalCount = (cocCount?.escalation ?? 0) + (cocCount?.waitingToClose ?? 0) + (cocCount?.waitingForAcceptance ?? 0) + (cocCount?.extendTATRequest ?? 0); + workListCounter += cocFinalCount; + } } + if (showLoading) Utils.hideLoading(context); notifyListeners(); } catch (ex) { @@ -188,7 +191,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Leave and Ticket Balance API's & Methods Future fetchLeaveTicketBalance(context, DateTime date) async { try { - accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(date)); + accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy", "en_US").format(date)); isLeaveTicketBalanceLoading = false; leaveBalanceAccrual = accrualList![0]; ticketBalance = (accrualList![1].accrualNetEntitlement ?? 0.0) + (accrualList![2].accrualNetEntitlement ?? 0.0) + (accrualList![3].accrualNetEntitlement ?? 0.0); @@ -210,12 +213,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List menuList = await DashboardApiClient().getListMenu(); List findMyRequest = menuList.where((element) => element.menuType == "E").toList(); if (findMyRequest.isNotEmpty) { - drawerMenuItemList.insert(3, DrawerMenuItem("assets/images/drawer/my_requests.svg", LocaleKeys.myRequest.tr(), AppRoutes.myRequests)); + drawerMenuItemList.add(DrawerMenuItem("assets/images/drawer/my_requests.svg", LocaleKeys.myRequest.tr(), AppRoutes.myRequests)); } List findMyTeam = menuList.where((element) => element.menuType == "M").toList(); if (findMyTeam.isNotEmpty) { AppState().setempStatusIsManager = true; - drawerMenuItemList.insert(2, DrawerMenuItem("assets/images/drawer/my_team.svg", LocaleKeys.myTeamMembers.tr(), AppRoutes.myTeam)); + drawerMenuItemList.add(DrawerMenuItem("assets/images/drawer/my_team.svg", LocaleKeys.myTeamMembers.tr(), AppRoutes.myTeam)); } } catch (ex) { logger.wtf(ex); @@ -231,10 +234,10 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { homeMenus = parseMenus(getMenuEntriesList ?? []); if (homeMenus!.isNotEmpty) { - if(env["dashboard"]["monthlyAttendance"]) { + if (env.dashboard.monthlyAttendance) { homeMenus!.first.menuEntiesList.insert(0, GetMenuEntriesList(requestType: "MONTHLY_ATTENDANCE", prompt: LocaleKeys.monthlyAttendance.tr())); } - if(env["dashboard"]["vocationRules"]) { + if (env.dashboard.vocationRules) { homeMenus!.first.menuEntiesList.add(GetMenuEntriesList(requestType: "VACATION_RULE", prompt: LocaleKeys.vacationRule.tr())); } } @@ -247,7 +250,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - void getCategoryOffersListAPI(BuildContext context) async { + void getCategoryOffersListAPI(BuildContext context) async { try { // Utils.showLoading(context); getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10); @@ -274,6 +277,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification(); return res; } + void notify() { notifyListeners(); } diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index 46d4d40..1753c29 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -432,7 +432,7 @@ class _MonthlyAttendanceScreenState extends State { expand: false, builder: (_, controller) { dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE; - DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString); + DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss", "en_US").parse(dmyString); return Column( children: [ Container( diff --git a/lib/ui/attendance/vacation_rule_screen.dart b/lib/ui/attendance/vacation_rule_screen.dart index 5598e05..af5b4cf 100644 --- a/lib/ui/attendance/vacation_rule_screen.dart +++ b/lib/ui/attendance/vacation_rule_screen.dart @@ -140,7 +140,7 @@ class _VacationRuleScreenState extends State { } String getParsedTime(String time) { - DateTime date = DateFormat("MM/dd/yyyy").parse(time); - return DateFormat("d MMM yyyy").format(date); + DateTime date = DateFormat("MM/dd/yyyy", "en_US").parse(time); + return DateFormat("d MMM yyyy", "en_US").format(date); } } diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart index 627c24a..2356e10 100644 --- a/lib/ui/chat/call/chat_outgoing_call_screen.dart +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -10,12 +10,14 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; +import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; +import 'package:provider/provider.dart'; class OutGoingCall extends StatefulWidget { - CallDataModel OutGoingCallData; - bool? isVideoCall; + CallDataModel outGoingCallData; + bool isVideoCall; - OutGoingCall({Key? key, required this.OutGoingCallData, this.isVideoCall}) : super(key: key); + OutGoingCall({Key? key, required this.outGoingCallData, required this.isVideoCall}) : super(key: key); @override _OutGoingCallState createState() => _OutGoingCallState(); @@ -23,23 +25,25 @@ class OutGoingCall extends StatefulWidget { class _OutGoingCallState extends State with SingleTickerProviderStateMixin { AnimationController? _animationController; - CameraController? _controller; + late CameraController controller; + late List _cameras; Future? _initializeControllerFuture; bool isCameraReady = false; bool isMicOff = false; bool isLoudSpeaker = false; bool isCamOff = false; + late ChatCallProvider callProviderd; @override void initState() { + callProviderd = Provider.of(context, listen: false); _animationController = AnimationController( vsync: this, duration: const Duration( milliseconds: 500, ), ); - logger.d(jsonEncode(widget.OutGoingCallData)); - //_runAnimation(); + // _runAnimation(); // connectSignaling(); WidgetsBinding.instance.addPostFrameCallback( (_) => _runAnimation(), @@ -58,13 +62,10 @@ class _OutGoingCallState extends State with SingleTickerProviderSt return Stack( alignment: FractionalOffset.center, children: [ - if (widget.isVideoCall!) + if (widget.isVideoCall) Positioned.fill( - child: AspectRatio( - aspectRatio: _controller!.value.aspectRatio, - child: CameraPreview( - _controller!, - ), + child: CameraPreview( + controller, ), ), Positioned.fill( @@ -74,7 +75,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt child: Container( decoration: BoxDecoration( color: MyColors.grey57Color.withOpacity( - 0.7, + 0.3, ), ), child: Column( @@ -105,9 +106,9 @@ class _OutGoingCallState extends State with SingleTickerProviderSt fit: BoxFit.cover, ), 10.height, - const Text( - "Aamir Saleem Ahmad", - style: TextStyle( + Text( + widget.outGoingCallData.title, + style: const TextStyle( fontSize: 21, fontWeight: FontWeight.bold, color: MyColors.white, @@ -179,7 +180,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (widget.isVideoCall!) + if (widget.isVideoCall) RawMaterialButton( onPressed: () { _camOff(); @@ -267,13 +268,10 @@ class _OutGoingCallState extends State with SingleTickerProviderSt } void _runAnimation() async { - List cameras = await availableCameras(); - CameraDescription firstCamera = cameras[1]; - _controller = CameraController( - firstCamera, - ResolutionPreset.medium, - ); - _initializeControllerFuture = _controller!.initialize(); + _cameras = await availableCameras(); + CameraDescription firstCamera = _cameras[1]; + controller = CameraController(firstCamera, ResolutionPreset.medium); + _initializeControllerFuture = controller.initialize(); setState(() {}); // setAudioFile(); for (int i = 0; i < 100; i++) { @@ -304,7 +302,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt try { // backToHome(); // final roomModel = RoomModel(name: widget.OutGoingCallData.name, token: widget.OutGoingCallData.sessionId, identity: widget.OutGoingCallData.identity); - await _controller?.dispose(); + await controller?.dispose(); // changeCallStatusAPI(4); diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index a72e12b..421eb91 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:audio_waveforms/audio_waveforms.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -13,7 +14,10 @@ import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; +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'; @@ -41,8 +45,10 @@ class ChatDetailScreen extends StatefulWidget { class _ChatDetailScreenState extends State { final RefreshController _rc = RefreshController(initialRefresh: false); late ChatProviderModel data; + late ChatCallProvider callPro; ChatDetailedScreenParams? params; - var textDirection = TextDirection.RTL; + + // var textDirection = TextDirection.RTL; void getMoreChat() async { if (params != null) { @@ -72,6 +78,7 @@ class _ChatDetailScreenState extends State { Widget build(BuildContext context) { params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams; data = Provider.of(context, listen: false); + // callPro = Provider.of(context, listen: false); if (params != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), @@ -92,11 +99,11 @@ class _ChatDetailScreenState extends State { chatUser: params!.chatUser, actions: [ // SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { - // // makeCall(callType: "AUDIO", con: hubConnection); + // makeCall(callType: "AUDIO"); // }), // 24.width, // SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() { - // // makeCall(callType: "VIDEO", con: hubConnection); + // makeCall(callType: "VIDEO"); // }), // 21.width, ], @@ -252,37 +259,39 @@ class _ChatDetailScreenState extends State { if (!m.isRecoding) Row( children: [ - TextField( - textDirection: m.textDirection, - controller: m.message, - decoration: InputDecoration( - hintTextDirection: m.textDirection, - hintText: m.isAttachmentMsg - ? m.selectedFile.path.split("/").last - : m.textDirection.name == "rtl" ? "اكتب هنا للرد" :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, + 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, ), - 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.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!); - }, - ).expanded, + onChanged: (String val) { + m.inputBoxDirection(val); + m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!); + }, + ).expanded, + ), if (m.sFileType.isNotEmpty) Row( children: [ @@ -342,45 +351,30 @@ class _ChatDetailScreenState extends State { } } - void makeCall({required String callType, required HubConnection con}) async { + void makeCall({required String callType}) async { + callPro.initCallListeners(); print("================== Make call Triggered ============================"); Map json = { "callerID": AppState().chatDetails!.response!.id!.toString(), - "callReceiverID": params!.chatUser!.id.toString(), - "notification_foreground": "true", - "message": "Aamir is calling", - "title": "Video Call", - "type": callType == "VIDEO" ? "Video" : "Audio", - "identity": AppState().chatDetails!.response!.userName, - "name": AppState().chatDetails!.response!.title, - "is_call": "true", - "is_webrtc": "true", - "contant": "Start video Call ${AppState().chatDetails!.response!.userName}", - "contantNo": "775d1f11-62d9-6fcc-91f6-21f8c14559fb", - "chatEventId": "3", - "fileTypeId": null, - "currentUserId": AppState().chatDetails!.response!.id!.toString(), - "chatSource": "1", - "userChatHistoryLineRequestList": [ - { - "isSeen": false, - "isDelivered": false, - "targetUserId": params!.chatUser!.id!, - "targetUserStatus": 4, - } - ], - // "server": "https://192.168.8.163:8086", - "server": "https://livecareturn.hmg.com:8086", + "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, + outGoingCallData: callData, ), ), - ); + ).then((value) { + print("then"); + callPro.stopListeners(); + }); } } diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 2e23254..9c5f216 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -52,11 +52,11 @@ class _ChatHomeState extends State { if (data.searchedChats == null || data.searchedChats!.isEmpty) { data.isLoading = true; data.getUserRecentChats().whenComplete(() async { - String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); - String notificationData = await Utils.getStringFromPrefs("notificationData"); - if (isAppOpendByChat != "null" || isAppOpendByChat == "true" && notificationData != "null") { - data.openChatByNoti(context); - } + // String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); + // String notificationData = await Utils.getStringFromPrefs("notificationData"); + // if (isAppOpendByChat != "null" || isAppOpendByChat == "true" && notificationData != "null") { + // data.openChatByNoti(context); + // } }); } } diff --git a/lib/ui/chat/custom_auto_direction.dart b/lib/ui/chat/custom_auto_direction.dart new file mode 100644 index 0000000..7e40644 --- /dev/null +++ b/lib/ui/chat/custom_auto_direction.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart' as intl; + +class CustomAutoDirection extends StatefulWidget { + final String text; + final Widget child; + final void Function(bool isRTL)? onDirectionChange; + + const CustomAutoDirection({Key? key, required this.text, required this.child, this.onDirectionChange}) : super(key: key); + + @override + _CustomAutoDirectionState createState() => _CustomAutoDirectionState(); +} + +class _CustomAutoDirectionState extends State { + late String text; + late Widget childWidget; + + @override + Widget build(BuildContext context) { + text = widget.text; + childWidget = widget.child; + return Directionality(textDirection: isRTL(text) ? TextDirection.rtl : TextDirection.ltr, child: childWidget); + } + + @override + void didUpdateWidget(CustomAutoDirection oldWidget) { + if (isRTL(oldWidget.text) != isRTL(widget.text)) { + WidgetsBinding.instance.addPostFrameCallback((_) => widget.onDirectionChange?.call(isRTL(widget.text))); + } + super.didUpdateWidget(oldWidget); + } + + bool isRTL(String text) { + if (text.isEmpty) return Directionality.of(context) == TextDirection.rtl; + return intl.Bidi.detectRtlDirectionality(text); + } +} diff --git a/lib/ui/dialogs/id/employee_digital_id_dialog.dart b/lib/ui/dialogs/id/employee_digital_id_dialog.dart index 0e672f8..63a5e29 100644 --- a/lib/ui/dialogs/id/employee_digital_id_dialog.dart +++ b/lib/ui/dialogs/id/employee_digital_id_dialog.dart @@ -6,10 +6,8 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; -import 'package:qr_flutter/qr_flutter.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/main.dart'; class EmployeeDigitialIdDialog extends StatelessWidget { @override diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 5ecfdf2..27cd5ff 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -61,13 +61,13 @@ class _DashboardScreenState extends State with WidgetsBindingOb super.initState(); scheduleMicrotask(() { data = Provider.of(context, listen: false); - if (env["marathon"]) { + if (env.marathon) { marathonProvider = Provider.of(context, listen: false); } - if (env["chat"]) { + if (env.chat) { cProvider = Provider.of(context, listen: false); + _bHubCon(); } - _bHubCon(); _onRefresh(true); }); } @@ -91,24 +91,28 @@ class _DashboardScreenState extends State with WidgetsBindingOb void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); - chatHubConnection.stop(); + if (!cProvider.disbaleChatForThisUser) { + chatHubConnection.stop(); + } } void _bHubCon() { cProvider.getUserAutoLoginToken().whenComplete(() async { - String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); - if (isAppOpendByChat != null && isAppOpendByChat == "true") { - Utils.showLoading(context); - cProvider.buildHubConnection(); - Future.delayed(const Duration(seconds: 2), () async { - cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); - gotoChat(context); - }); - } else { - cProvider.buildHubConnection(); - Future.delayed(const Duration(seconds: 2), () { - cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); - }); + if (!cProvider.disbaleChatForThisUser) { + String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); + if (isAppOpendByChat != null && isAppOpendByChat == "true") { + Utils.showLoading(context); + cProvider.buildHubConnection(); + Future.delayed(const Duration(seconds: 2), () async { + cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); + gotoChat(context); + }); + } else { + cProvider.buildHubConnection(); + Future.delayed(const Duration(seconds: 2), () { + cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); + }); + } } }); } @@ -137,21 +141,25 @@ class _DashboardScreenState extends State with WidgetsBindingOb // print(value.result!.data!.notificationTitle); // }); data.fetchListMenu(); - if (env["dashboard"]["attendance"]) { + if (env.dashboard.attendance) { data.fetchAttendanceTracking(context); } data.fetchWorkListCounter(context); - if (env["dashboard"]["missingSwipe"]) { + if (env.dashboard.missingSwipe) { data.fetchMissingSwipe(context); } data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); - data.getCategoryOffersListAPI(context); - if (env["marathon"]) { + if (env.offersDiscount) { + data.getCategoryOffersListAPI(context); + } + if (env.marathon) { marathonProvider.getMarathonDetailsFromApi(); } - - if (!isFromInit) checkHubCon(); + if (env.chat) { + marathonProvider.getMarathonDetailsFromApi(); + if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon(); + } _refreshController.refreshCompleted(); } @@ -235,12 +243,12 @@ class _DashboardScreenState extends State with WidgetsBindingOb }); }), Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, - SvgPicture.asset( - "assets/images/announcements.svg", - matchTextDirection: true, - ).onPress(() async { - await Navigator.pushNamed(context, AppRoutes.announcements); - }) + // SvgPicture.asset( + // "assets/images/announcements.svg", + // matchTextDirection: true, + // ).onPress(() async { + // await Navigator.pushNamed(context, AppRoutes.announcements); + // }) ], ).paddingOnly(left: 21, right: 21, top: 48, bottom: 7), Expanded( @@ -265,119 +273,119 @@ class _DashboardScreenState extends State with WidgetsBindingOb 16.height, Row( children: [ - if (env["dashboard"]["attendance"]) - Expanded( - child: AspectRatio( - aspectRatio: 159 / 159, - child: Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - return (model.isAttendanceTrackingLoading - ? GetAttendanceTrackingShimmer() - : Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(15), - gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ]), - ), - child: Stack( - alignment: Alignment.center, - children: [ - if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + if (env.dashboard.attendance) + Expanded( + child: AspectRatio( + aspectRatio: 159 / 159, + child: Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + return (model.isAttendanceTrackingLoading + ? GetAttendanceTrackingShimmer() + : Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ]), + ), + child: Stack( + alignment: Alignment.center, + children: [ + if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true), + if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white), + if (model.isTimeRemainingInSeconds != 0) + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 9.height, + Directionality( + textDirection: ui.TextDirection.ltr, + child: CountdownTimer( + endTime: model.endTime, + onEnd: null, + endWidget: "00:00:00".toText14(color: Colors.white, isBold: true), + textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold), + ), + ), + LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white), + 9.height, + ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(20)), + child: LinearProgressIndicator( + value: model.progress, + minHeight: 8, + valueColor: const AlwaysStoppedAnimation(Colors.white), + backgroundColor: const Color(0xff196D73), + ), + ), + ], + ), + ], + ).paddingOnly(top: 12, right: 15, left: 12), + ), + Row( children: [ - LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true), - if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white), - if (model.isTimeRemainingInSeconds != 0) - Column( + Expanded( + child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - 9.height, - Directionality( - textDirection: ui.TextDirection.ltr, - child: CountdownTimer( - endTime: model.endTime, - onEnd: null, - endWidget: "00:00:00".toText14(color: Colors.white, isBold: true), - textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold), - ), - ), - LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white), - 9.height, - ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(20)), - child: LinearProgressIndicator( - value: model.progress, - minHeight: 8, - valueColor: const AlwaysStoppedAnimation(Colors.white), - backgroundColor: const Color(0xff196D73), - ), - ), + LocaleKeys.checkIn.tr().toText12(color: Colors.white), + (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) + .toString() + .toText14(color: Colors.white, isBold: true), + 4.height, ], + ).paddingOnly(left: 12, right: 12), + ), + Container( + margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), + width: 45, + height: 45, + padding: const EdgeInsets.only(left: 10, right: 10), + decoration: BoxDecoration( + color: Color(0xff259EA4), + borderRadius: BorderRadius.only( + bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), + ), ), + child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/attendance.svg" : "assets/images/attendance.svg"), + ).onPress(() { + showMyBottomSheet( + context, + callBackFunc: () {}, + child: MarkAttendanceWidget(model, isFromDashboard: true), + ); + }), ], - ).paddingOnly(top: 12, right: 15, left: 12), - ), - Row( - children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.checkIn.tr().toText12(color: Colors.white), - (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) - .toString() - .toText14(color: Colors.white, isBold: true), - 4.height, - ], - ).paddingOnly(left: 12, right: 12), - ), - Container( - margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), - width: 45, - height: 45, - padding: const EdgeInsets.only(left: 10, right: 10), - decoration: BoxDecoration( - color: Color(0xff259EA4), - borderRadius: BorderRadius.only( - bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), - bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), - ), - ), - child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/attendance.svg" : "assets/images/attendance.svg"), - ).onPress(() { - showMyBottomSheet( - context, - callBackFunc: () {}, - child: MarkAttendanceWidget(model, isFromDashboard: true), - ); - }), - ], - ), - ], - ), - ], - ), - ).onPress( - () { - Navigator.pushNamed(context, AppRoutes.todayAttendance); - }, - )) - .animatedSwither(); - }, + ), + ], + ), + ], + ), + ).onPress( + () { + Navigator.pushNamed(context, AppRoutes.todayAttendance); + }, + )) + .animatedSwither(); + }, + ), ), ), - ), - if (env["dashboard"]["attendance"]) 9.width, + if (env.dashboard.attendance) 9.width, Expanded( child: MenusWidget(), ), @@ -385,102 +393,105 @@ class _DashboardScreenState extends State with WidgetsBindingOb ), ], ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - LocaleKeys.offers.tr().toText12(), - Row( - children: [ - LocaleKeys.discounts.tr().toText24(isBold: true), - 6.width, - Container( - padding: const EdgeInsets.only(left: 8, right: 8), - decoration: BoxDecoration( - color: MyColors.yellowColor, - borderRadius: BorderRadius.circular(10), - ), - child: LocaleKeys.newString.tr().toText10(isBold: true)), - ], - ), - ], + Visibility( + visible: env.offersDiscount, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + LocaleKeys.offers.tr().toText12(), + Row( + children: [ + LocaleKeys.discounts.tr().toText24(isBold: true), + 6.width, + Container( + padding: const EdgeInsets.only(left: 8, right: 8), + decoration: BoxDecoration( + color: MyColors.yellowColor, + borderRadius: BorderRadius.circular(10), + ), + child: LocaleKeys.newString.tr().toText10(isBold: true)), + ], + ), + ], + ), ), - ), - LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { - Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - }) - ], - ).paddingOnly(left: 21, right: 21), - Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - return SizedBox( - height: 103 + 33, - child: ListView.separated( - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.only(left: 21, right: 21, top: 13), - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext cxt, int index) { - return model.isOffersLoading - ? const OffersShimmerWidget() - : InkWell( - onTap: () { - navigateToDetails(data.getOffersList[index]); - }, - child: SizedBox( - width: 73, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 73, - height: 73, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all( - Radius.circular(100), - ), - border: Border.all(color: MyColors.lightGreyE3Color, width: 1), - ), - child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(50), + LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }) + ], + ).paddingOnly(left: 21, right: 21), + Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + return SizedBox( + height: 103 + 33, + child: ListView.separated( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.only(left: 21, right: 21, top: 13), + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext cxt, int index) { + return model.isOffersLoading + ? const OffersShimmerWidget() + : InkWell( + onTap: () { + navigateToDetails(data.getOffersList[index]); + }, + child: SizedBox( + width: 73, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 73, + height: 73, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), + border: Border.all(color: MyColors.lightGreyE3Color, width: 1), ), - child: Hero( - tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, - transitionOnUserGestures: true, - child: Image.network( - data.getOffersList[index].bannerImage!, - fit: BoxFit.contain, + child: ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + child: Hero( + tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, + transitionOnUserGestures: true, + child: Image.network( + data.getOffersList[index].logo!, + fit: BoxFit.contain, + ), ), ), ), - ), - 4.height, - Expanded( - child: AppState().isArabic(context) - ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) - : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), - ), - ], + 4.height, + Expanded( + child: AppState().isArabic(context) + ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) + : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + ), + ], + ), ), - ), - ); - }, - separatorBuilder: (BuildContext cxt, int index) => 8.width, - itemCount: 9), - ); - }, - ), - ], + ); + }, + separatorBuilder: (BuildContext cxt, int index) => 8.width, + itemCount: 9), + ); + }, + ), + ], + ), ), Container( width: double.infinity, @@ -493,9 +504,8 @@ class _DashboardScreenState extends State with WidgetsBindingOb child: Column( mainAxisSize: MainAxisSize.min, children: [ - - if (env["marathon"]) - context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8), + if (env.marathon) + context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8), ServicesWidget(), ], ), @@ -510,110 +520,116 @@ class _DashboardScreenState extends State with WidgetsBindingOb drawer: SafeArea( child: AppDrawer(onLanguageChange: _onRefresh), ), - bottomNavigationBar:!env["bottomBar"] + bottomNavigationBar: !env.bottomBar ? null : SizedBox( - height: Platform.isAndroid ? 70 : 100, - child: BottomNavigationBar( - items: [ - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/home.svg", - color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.home.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/create_req.svg", - color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.mowadhafhiRequest.tr(), - ), - BottomNavigationBarItem( - icon: Stack( - alignment: Alignment.centerLeft, - children: [ - SvgPicture.asset( - "assets/icons/work_list.svg", - color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - Consumer( - builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { - if (data.workListCounter == 0) { - return const SizedBox(); - } - return Positioned( - right: 0, - top: 0, - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - alignment: Alignment.center, - decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.workListCounter.toString().toText10(color: Colors.white), + height: Platform.isAndroid ? 70 : 100, + child: BottomNavigationBar( + items: [ + BottomNavigationBarItem( + icon: SvgPicture.asset( + "assets/icons/home.svg", + color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color, + ).paddingAll(4), + label: LocaleKeys.home.tr(), + ), + BottomNavigationBarItem( + icon: SvgPicture.asset( + "assets/icons/create_req.svg", + color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color, + ).paddingAll(4), + label: LocaleKeys.mowadhafhiRequest.tr(), + ), + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/work_list.svg", + color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color, + ).paddingAll(4), + Consumer( + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + if (data.workListCounter == 0) { + return const SizedBox(); + } + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.workListCounter.toString().toText10(color: Colors.white), + ), + ); + }, ), - ); - }, + ], + ), + label: LocaleKeys.workList.tr(), ), - ], - ), - label: LocaleKeys.workList.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/item_for_sale.svg", - color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.itemsForSale.tr(), - ), - BottomNavigationBarItem( - icon: Stack( - alignment: Alignment.centerLeft, - children: [ - SvgPicture.asset( - "assets/icons/chat/chat.svg", - color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - Consumer( - builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { - return Positioned( - right: 0, - top: 0, - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - alignment: Alignment.center, - decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.chatUConvCounter.toString().toText10(color: Colors.white), + BottomNavigationBarItem( + icon: SvgPicture.asset( + "assets/icons/item_for_sale.svg", + color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color, + ).paddingAll(4), + label: LocaleKeys.itemsForSale.tr(), + ), + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/chat/chat.svg", + color: currentIndex == 4 + ? MyColors.grey3AColor + : cProvider.disbaleChatForThisUser + ? MyColors.lightGreyE3Color + : MyColors.grey98Color, + ).paddingAll(4), + Consumer( + builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: cProvider.disbaleChatForThisUser ? MyColors.pinkDarkColor : MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.chatUConvCounter.toString().toText10(color: Colors.white), + ), + ); + }, ), - ); - }, + ], + ), + label: LocaleKeys.chat.tr(), ), ], + currentIndex: currentIndex, + selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), + unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), + type: BottomNavigationBarType.fixed, + selectedItemColor: MyColors.grey3AColor, + backgroundColor: MyColors.backgroundColor, + selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), + unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), + onTap: (int index) { + if (index == 1) { + Navigator.pushNamed(context, AppRoutes.mowadhafhi); + } else if (index == 2) { + Navigator.pushNamed(context, AppRoutes.workList); + } else if (index == 3) { + Navigator.pushNamed(context, AppRoutes.itemsForSale); + } else if (index == 4) { + if (!cProvider.disbaleChatForThisUser) { + Navigator.pushNamed(context, AppRoutes.chat); + } + } + }, ), - label: LocaleKeys.chat.tr(), ), - ], - currentIndex: currentIndex, - selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), - unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), - type: BottomNavigationBarType.fixed, - selectedItemColor: MyColors.grey3AColor, - backgroundColor: MyColors.backgroundColor, - selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), - unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), - onTap: (int index) { - if (index == 1) { - Navigator.pushNamed(context, AppRoutes.mowadhafhi); - } else if (index == 2) { - Navigator.pushNamed(context, AppRoutes.workList); - } else if (index == 3) { - Navigator.pushNamed(context, AppRoutes.itemsForSale); - } else if (index == 4) { - Navigator.pushNamed(context, AppRoutes.chat); - } - }, - ), - ), ); } diff --git a/lib/ui/landing/widget/app_drawer.dart b/lib/ui/landing/widget/app_drawer.dart index 7df697c..2b8e034 100644 --- a/lib/ui/landing/widget/app_drawer.dart +++ b/lib/ui/landing/widget/app_drawer.dart @@ -5,6 +5,7 @@ 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/env.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'; @@ -29,12 +30,14 @@ class AppDrawer extends StatefulWidget { class _AppDrawerState extends State { List drawerMenuItemList = []; - late ChatProviderModel chatData; + ChatProviderModel? chatData; @override void initState() { super.initState(); - chatData = Provider.of(context, listen: false); + if (env.chat) { + chatData = Provider.of(context, listen: false); + } } @override @@ -117,9 +120,10 @@ class _AppDrawerState extends State { Navigator.pushNamed(context, drawerMenuItemList[index].routeName); }); }), - 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/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/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,); ], @@ -175,7 +179,7 @@ class _AppDrawerState extends State { AppState().isAuthenticated = false; AppState().isLogged = false; AppState().setPostParamsInitConfig(); - chatData.disposeData(); + chatData?.disposeData(); // SharedPreferences prefs = await SharedPreferences.getInstance(); // await prefs.clear(); Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: null); diff --git a/lib/ui/landing/widget/menus_widget.dart b/lib/ui/landing/widget/menus_widget.dart index 51cb3c7..2a0f2be 100644 --- a/lib/ui/landing/widget/menus_widget.dart +++ b/lib/ui/landing/widget/menus_widget.dart @@ -53,7 +53,7 @@ class MenusWidget extends StatelessWidget { ).onPress(() { Navigator.pushNamed(context, AppRoutes.workList); }), - if(env["dashboard"]["missingSwipe"]) + if(env.dashboard.missingSwipe) data.isMissingSwipeLoading ? MenuShimmer().onPress(() { data.fetchWorkListCounter(context); @@ -108,7 +108,7 @@ class MenusWidget extends StatelessWidget { ).onPress(() { Navigator.pushNamed(context, AppRoutes.leaveBalance); }), - if(env["dashboard"]["ticketBalance"]) + if(env.dashboard.ticketBalance) data.isLeaveTicketBalanceLoading ? MenuShimmer().onPress(() { data.fetchWorkListCounter(context); diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index cf79e70..b93035f 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; @@ -69,7 +71,10 @@ class ServicesWidget extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SvgPicture.asset(AppState().isArabic(context) ? getMenuIconAr(data.homeMenus![parentIndex].menuEntiesList[index].prompt!) : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)), + Image.memory( + Base64Decoder().convert(data.homeMenus![parentIndex].menuEntiesList[index].icon ?? ""), + scale: 1.25, + ), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index a16e81d..d8ba32f 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -313,6 +313,7 @@ class _AddLeaveBalanceScreenState extends State { model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, + length: model.mAXIMUMSIZE, onChange: (text) { model.eSERVICESDV ??= ESERVICESDV(); model.eSERVICESDV!.pIDCOLUMNNAME = text; @@ -501,6 +502,7 @@ class _AddLeaveBalanceScreenState extends State { (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", + length: model.mAXIMUMSIZE, onChange: (text) { //model.fieldAnswer = text; }, diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index d513868..3bb894d 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -8,6 +8,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -20,7 +21,6 @@ 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/check_mobile_app_version_model.dart'; import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; @@ -28,7 +28,6 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/input_widget.dart'; -import 'package:permission_handler/permission_handler.dart'; import 'package:safe_device/safe_device.dart'; import 'package:wifi_iot/wifi_iot.dart'; @@ -59,9 +58,12 @@ class _LoginScreenState extends State { bool isOnExternalStorage = false; bool isDevelopmentModeEnable = false; + late HmsApiAvailability hmsApiAvailability; + @override void initState() { super.initState(); + hmsApiAvailability = HmsApiAvailability(); // checkFirebaseToken(); // if (kReleaseMode) { // checkDeviceSafety(); @@ -95,27 +97,27 @@ class _LoginScreenState extends State { Future checkFirebaseToken() async { try { Utils.showLoading(context); - await Firebase.initializeApp(); - // await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( - // alert: true, - // badge: true, - // sound: true, - // ); - // await FirebaseMessaging.instance.requestPermission(); - _firebaseMessaging = FirebaseMessaging.instance; - firebaseToken = await _firebaseMessaging.getToken(); - AppNotifications().init(firebaseToken); - loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios"); - if (loginInfo == null) { - await checkPrefs(); - _autoLogin = false; - Utils.hideLoading(context); - return; + if (Platform.isAndroid) { + try { + await hmsApiAvailability.isHMSAvailable().then((value) async { + if (value == 0) { + AppState().setIsHuawei = true; + AppNotifications().initHuaweiPush(checkLoginInfo); + } else { + await Firebase.initializeApp(); + _firebaseMessaging = FirebaseMessaging.instance; + firebaseToken = await _firebaseMessaging.getToken(); + AppNotifications().init(firebaseToken); + checkLoginInfo(); + } + }); + } catch (ex) {} } else { - loginInfo!.deviceToken = firebaseToken; - await checkPrefs(); - Utils.hideLoading(context); - performLogin(); + await Firebase.initializeApp(); + _firebaseMessaging = FirebaseMessaging.instance; + firebaseToken = await _firebaseMessaging.getToken(); + AppNotifications().init(firebaseToken); + checkLoginInfo(); } } catch (ex) { Utils.hideLoading(context); @@ -123,9 +125,24 @@ class _LoginScreenState extends State { } } + void checkLoginInfo() async { + loginInfo = await LoginApiClient().getMobileLoginInfoNEW(AppState().getIsHuawei ? AppState().getHuaweiPushToken : firebaseToken ?? "", Platform.isAndroid ? "android" : "ios"); + if (loginInfo == null) { + await checkPrefs(); + _autoLogin = false; + Utils.hideLoading(context); + return; + } else { + loginInfo!.deviceToken = firebaseToken; + await checkPrefs(); + Utils.hideLoading(context); + performLogin(); + } + } + Future checkPrefs() async { String username = await Utils.getStringFromPrefs(SharedPrefsConsts.username); - if (username.isNotEmpty) { + if (!username.isNotEmpty) { // for test purpose i added ! String password = await Utils.getStringFromPrefs(SharedPrefsConsts.password); // String firebaseToken = await Utils.getStringFromPrefs(SharedPrefsConsts.firebaseToken); // print("firebaseToken:$firebaseToken"); @@ -166,22 +183,29 @@ class _LoginScreenState extends State { } } - @override Widget build(BuildContext context) { if (isAppOpenBySystem == null) { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; if (!kReleaseMode) { - // username.text = "15444"; // Maha User - // username.text = "15153"; // Tamer User - // password.text = "Abcd@1234"; - - - username.text = "SRCA4779T"; // Hashim User - password.text = "a12345"; + username.text = "1100313582"; + password.text = "moe123456"; - username.text = "SRCA04101"; // Hashim User - password.text = "a123456"; + // 1) Normal user : + // Username: 1100313582 + // Employee # and Name: 210624 - شهد خالد ابراهيم الشامخ + // Password: moe123456 + // + // 2) Normal user : + // Username: 1002528733 + // Employee # and Name: 221142 - فؤاد محمدامين بكر موسى + // moe123456 + // + // + // 3) HR User Account + // Username: 1087779144 + // Employee # and Name: 190089 - عبدالله عبدالرحمن محمد الشهري + // Password: moe123456 } if (isAppOpenBySystem!) checkFirebaseToken(); } @@ -232,7 +256,7 @@ class _LoginScreenState extends State { 12.height, InputWidget(LocaleKeys.password.tr(), "xxxxxx", password, isTextIsPassword: true), 9.height, - if (env["login"]["forgetPassword"]) + if (env.login.forgetPassword) Align( alignment: Alignment.centerRight, child: LocaleKeys.forgotPassword.tr().toText12(isUnderLine: true, color: MyColors.textMixColor).onPress(() { diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index 30feb71..8eca069 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -11,6 +11,7 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/env.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/dialogs/otp_dialog.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -141,7 +142,7 @@ class _VerifyLastLoginScreenState extends State { children: [ if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3), if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4), - getButton(2), + if (env.login.verificationMethod.whatsapp) getButton(2), getButton(1), ], ) @@ -364,7 +365,7 @@ class _VerifyLastLoginScreenState extends State { Future performDirectApiCall(String _title, String _icon, int _flag, String value, TextEditingController? _pinPutController, {bool isDirectLogin = false}) async { try { - GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); + GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( AppState().memberLoginList?.pEMAILADDRESS ?? "", genericResponseModel?.pSESSIONID ?? 0, @@ -372,7 +373,7 @@ class _VerifyLastLoginScreenState extends State { _flag, AppState().memberLoginList?.pMOBILENUMBER ?? "", AppState().getUserName!, - mobileLoginInfoListModel!.deviceToken!, + AppState().getIsHuawei ? AppState().getHuaweiPushToken : mobileLoginInfoListModel!.deviceToken!, Platform.isAndroid ? "android" : "ios"); AppState().setMemberInformationListModel = genericResponseModel!.memberInformationList?.first; AppState().setPrivilegeListModel = genericResponseModel!.privilegeList ?? []; diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index 6cce7c1..febd06b 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -79,7 +79,7 @@ class _VerifyLoginScreenState extends State { children: [ if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3), if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4), - if (env["login"]["verificationMethod"]["whatsapp"]) getButton(2), + if (env.login.verificationMethod.whatsapp) getButton(2), getButton(1), ], ) @@ -620,7 +620,7 @@ class _VerifyLoginScreenState extends State { int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), (value, TextEditingController _pinPutController) async { Utils.showLoading(context); - try { + try { GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( AppState().memberLoginList?.pEMAILADDRESS ?? "", @@ -629,7 +629,7 @@ class _VerifyLoginScreenState extends State { _flag, AppState().memberLoginList?.pMOBILENUMBER ?? "", AppState().getUserName!, - firebaseToken!, + AppState().getIsHuawei ? AppState().getHuaweiPushToken : firebaseToken!, Platform.isAndroid ? "android" : "ios"); if (genericResponseModel?.errorMessage != null) { Utils.showToast(genericResponseModel?.errorMessage ?? ""); @@ -638,13 +638,13 @@ class _VerifyLoginScreenState extends State { AppState().setMemberInformationListModel = genericResponseModel.memberInformationList?.first; MemberInformationListModel.saveToPrefs(genericResponseModel.memberInformationList ?? []); PrivilegeListModel.saveToPrefs(genericResponseModel.privilegeList ?? []); - AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID; - AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; - AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; + // AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID; + // AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; + // AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; Utils.saveStringFromPrefs(SharedPrefsConsts.username, AppState().getUserName!); Utils.saveStringFromPrefs(SharedPrefsConsts.password, AppState().password!); - Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID!); - Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiPassword, genericResponseModel.mohemmWifiPassword!); + // Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID ?? ""); + // Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiPassword, genericResponseModel.mohemmWifiPassword!); } Utils.hideLoading(context); Navigator.pop(context); diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 856a484..34d8cc9 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'package:appinio_swiper/appinio_swiper.dart'; import 'package:flutter/cupertino.dart'; @@ -134,6 +135,7 @@ class MarathonProvider extends ChangeNotifier { late VideoPlayerController videoController; Future initializeVideoPlayer() async { + log("VIDEO PLAYER INITIALIZED!!!"); videoController = VideoPlayerController.network(ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.video!); await videoController.initialize(); await videoController.play(); diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index f4207a1..22a15de 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -169,7 +169,6 @@ class MarathonScreen extends StatelessWidget { ], ) : const SizedBox(), - 34.height, if (provider.selectedWinners != null) ...[ provider.selectedWinners!.length == 1 ? Column( @@ -179,7 +178,7 @@ class MarathonScreen extends StatelessWidget { isCentered: true, ), 8.height, - AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color), + provider.selectedWinners![0].employeeId!.toText22(color: MyColors.grey57Color), ], ) : ListView.separated( @@ -310,7 +309,7 @@ class MarathonScreen extends StatelessWidget { else ...[ MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), ], - if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ + if (provider.questionCardStatus == QuestionCardStatus.findingWinner && !provider.isUserOutOfGame) ...[ getNameContainer(context), ], QuestionCardBuilder( @@ -337,7 +336,7 @@ class MarathonScreen extends StatelessWidget { subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor, isCentered: true), ), onFindingWinner: (BuildContext context) => CustomStatusWidget( - asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168, reverse: false), + asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168, reverse: false, repeat: true), title: LocaleKeys.fingersCrossed.tr().toText22(color: MyColors.greenColor), subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor, isCentered: true), ), diff --git a/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart b/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart index c12a452..5c34b6a 100644 --- a/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart +++ b/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart @@ -123,10 +123,13 @@ class CountdownTimerForDetailScreen extends StatelessWidget { Widget buildCountdownTimer(CurrentRemainingTime? time) { if (provider.marathonDetailModel.startTime != null) { int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes; - if (remainingTimeInMinutes <= 30) { - scheduleMicrotask(() { + if (remainingTimeInMinutes <= 30 && provider.canPlayDemo == true) { + // scheduleMicrotask(() { + // print("Timer TRUE!!!: ${time?.min.toString()}"); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { provider.canPlayDemo = false; }); + // }); } } diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index f9076bc..ecce777 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -347,7 +347,10 @@ class MarathonBanner extends StatelessWidget { @override Widget build(BuildContext context) { MarathonProvider provider = context.read(); - + // if(provider.isUserWaiting) { + // provider.isUserWaiting = false; + // provider.getMarathonDetailsFromApi(); + // } return !provider.isPrivilegedWithMarathon ? getUnPrivilegedMarathon(context) : provider.isUpComingMarathon @@ -524,6 +527,8 @@ class MarathonBanner extends StatelessWidget { int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes; if (remainingTimeInMinutes > 5 && provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) { + log("IF CALLED!!!"); + log("Remaining Time: $remainingTimeInMinutes"); Utils.showLoading(context); try { await provider.initializeVideoPlayer().then((_) { @@ -532,14 +537,19 @@ class MarathonBanner extends StatelessWidget { Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen); }); } catch (e) { - if (kDebugMode) { + // if (kDebugMode) { log("Error in VideoPlayer: ${e.toString()}"); - } + // } Utils.hideLoading(context); - Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen).then((value) { + print("Back to home!!!"); + }); } } else { - Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + log("ELSE CALLED!!!"); + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen).then((value) { + print("Back to home!!!"); + }); } }), ) diff --git a/lib/ui/marathon/widgets/marathon_progress_container.dart b/lib/ui/marathon/widgets/marathon_progress_container.dart index 3de86ce..17f9d1c 100644 --- a/lib/ui/marathon/widgets/marathon_progress_container.dart +++ b/lib/ui/marathon/widgets/marathon_progress_container.dart @@ -66,7 +66,11 @@ class MarathonProgressContainer extends StatelessWidget { stepper( provider.currentQuestionNumber, provider.answerStatusesList, - AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions! : provider.marathonDetailModel.totalQuestions!, + (provider.demoMarathonDetailModel.totalQuestions != null || provider.marathonDetailModel.totalQuestions != null) + ? AppState().getIsDemoMarathon + ? provider.demoMarathonDetailModel.totalQuestions! + : provider.marathonDetailModel.totalQuestions! + : 10, provider.isUserOutOfGame, ), 8.height, 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 4d11bb8..8451764 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -67,8 +67,8 @@ class _DynamicInputScreenState extends State { tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; if (tempVar.isNotEmpty) { if (!tempVar.contains("/")) { - DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar); + tempVar = DateFormat('yyyy/MM/dd HH:mm:ss', "en_US").format(date); } } } @@ -492,6 +492,8 @@ class _DynamicInputScreenState extends State { model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, + length: model.mAXIMUMSIZE, + toolTip: model.rEQCOLTIP, onChange: (text) { model.fieldAnswer = text; model.eSERVICESDV ??= ESERVICESDV(); @@ -506,7 +508,7 @@ class _DynamicInputScreenState extends State { displayText = displayText.replaceAll(" 00:00:00", ""); } if (displayText.contains("/")) { - displayText = DateFormat('yyyy-MM-dd').format(DateFormat("yyyy/MM/dd").parse(displayText)); + displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText)); } } return DynamicTextFieldWidget( @@ -514,10 +516,11 @@ class _DynamicInputScreenState extends State { displayText, suffixIconData: Icons.calendar_today, isEnable: false, + toolTip: model.rEQCOLTIP, onTap: () async { if ((getEitDffStructureList![index].eSERVICESDV?.pVALUECOLUMNNAME != null)) { if (getEitDffStructureList![index].isDefaultTypeIsCDPS) { - selectedDate = DateFormat("yyyy/MM/dd").parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", "")); + 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!); } @@ -576,9 +579,9 @@ class _DynamicInputScreenState extends State { tempDate = tempDate.replaceAll("00:00:00", '').trim(); } if (tempDate.contains("/")) { - selectedDate = DateFormat("yyyy/MM/dd").parse(tempDate); + selectedDate = DateFormat("yyyy/MM/dd", "en_US").parse(tempDate); } else { - selectedDate = DateFormat("yyyy-MM-dd").parse(tempDate); + selectedDate = DateFormat("yyyy-MM-dd", "en_US").parse(tempDate); } } else { selectedDate = DateTime.parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!); @@ -689,6 +692,7 @@ class _DynamicInputScreenState extends State { (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", + length: model.mAXIMUMSIZE, onChange: (text) { model.fieldAnswer = text; }, @@ -700,7 +704,7 @@ class _DynamicInputScreenState extends State { displayText = displayText.replaceAll(" 00:00:00", ""); } if (!displayText.contains("-")) { - displayText = DateFormat('yyyy-MM-dd').format(DateFormat("yyyy/MM/dd").parse(displayText)); + displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText)); } } return DynamicTextFieldWidget( diff --git a/lib/ui/my_team/view_attendance.dart b/lib/ui/my_team/view_attendance.dart index 0896d5e..a45f35c 100644 --- a/lib/ui/my_team/view_attendance.dart +++ b/lib/ui/my_team/view_attendance.dart @@ -159,7 +159,7 @@ class _ViewAttendanceState extends State { children: [ Row( children: [ - "${DateFormat("MMMM-yyyy").format(formattedDate)}".toText16(color: MyColors.grey3AColor), + "${DateFormat("MMMM-yyyy", "en_US").format(formattedDate)}".toText16(color: MyColors.grey3AColor), const Icon(Icons.keyboard_arrow_down_rounded, color: MyColors.grey3AColor), ], ).onPress( @@ -439,7 +439,7 @@ class _ViewAttendanceState extends State { expand: false, builder: (_, controller) { dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE; - DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString); + DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss", "en_US").parse(dmyString); return Column( children: [ Container( @@ -468,7 +468,7 @@ class _ViewAttendanceState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "${DateFormat("MMMM-dd-yyyy").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white), + "${DateFormat("MMMM-dd-yyyy", "en_US").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white), LocaleKeys.attendanceDetails.tr().toText16(color: MyColors.greyACColor), 12.height, CircularStepProgressBar( diff --git a/lib/ui/payslip/monthly_pay_slip_screen.dart b/lib/ui/payslip/monthly_pay_slip_screen.dart index 543d81c..5289390 100644 --- a/lib/ui/payslip/monthly_pay_slip_screen.dart +++ b/lib/ui/payslip/monthly_pay_slip_screen.dart @@ -105,7 +105,7 @@ class _MonthlyPaySlipScreenState extends State { Container(alignment: Alignment.centerLeft, child: LocaleKeys.month.tr().toText17(isBold: true, color: MyColors.darkIconColor)), Row( children: [ - DateFormat("MMMM-yyyy").format(DateFormat("MM/dd/yyyy").parse(paySlipList[selectedMonthIndex!].pAYMENTDATE!)).toText16(color: MyColors.greyACColor), + DateFormat("MMMM-yyyy", "en_US").format(DateFormat("MM/dd/yyyy", "en_US").parse(paySlipList[selectedMonthIndex!].pAYMENTDATE!)).toText16(color: MyColors.greyACColor), const Icon(Icons.keyboard_arrow_down_rounded, color: MyColors.greyACColor), ], ).onPress(() async { diff --git a/lib/ui/profile/add_update_family_member.dart b/lib/ui/profile/add_update_family_member.dart index 6263b95..442f529 100644 --- a/lib/ui/profile/add_update_family_member.dart +++ b/lib/ui/profile/add_update_family_member.dart @@ -238,7 +238,7 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = (DateFormat('yyyy-MM-dd').format(dateValue)); + date = (DateFormat('yyyy-MM-dd', "en_US").format(dateValue)); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; setState(() {}); }, @@ -286,6 +286,7 @@ class _AddUpdateFamilyMemberState extends State { (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.getContactDetailsList!.sEGMENTVALUEDSP ?? "", isInputTypeNum: true, + length: model.mAXIMUMSIZE, onChange: (String text) { model.getContactDetailsList!.sEGMENTVALUEDSP = text; }, @@ -298,7 +299,7 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = (DateFormat('yyyy-MM-dd').format(dateValue)); + date = (DateFormat('yyyy-MM-dd', "en_US").format(dateValue)); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; setState(() {}); }, @@ -345,6 +346,7 @@ class _AddUpdateFamilyMemberState extends State { (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.getContactDetailsList!.sEGMENTVALUEDSP ?? "", isInputTypeNum: true, + length: model.mAXIMUMSIZE, onChange: (String text) { model.getContactDetailsList!.sEGMENTVALUEDSP = text; }, @@ -357,7 +359,7 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = (DateFormat('yyyy-MM-dd').format(dateValue)); + date = (DateFormat('yyyy-MM-dd', "en_US").format(dateValue)); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; setState(() {}); }, diff --git a/lib/ui/profile/contact_details.dart b/lib/ui/profile/contact_details.dart index 749978e..c8631a7 100644 --- a/lib/ui/profile/contact_details.dart +++ b/lib/ui/profile/contact_details.dart @@ -5,6 +5,7 @@ import 'package:mohem_flutter_app/api/profile_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/env.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'; @@ -100,6 +101,7 @@ class _ContactDetailsState extends State { ), separatorBuilder: (cxt, index) => 12.height, itemCount: getEmployeePhonesList.length), + if(env.canEdit) if (menuEntriesPhone.updateButton == 'Y') AppState().isArabic(context) ? Positioned( @@ -131,6 +133,7 @@ class _ContactDetailsState extends State { ), separatorBuilder: (cxt, index) => 12.height, itemCount: getEmployeeAddressList.length), + if(env.canEdit) if (menuEntriesAddress.updateButton == 'Y') AppState().isArabic(context) ? Positioned( @@ -148,6 +151,7 @@ class _ContactDetailsState extends State { else Stack( children: [ + if(env.canEdit) if (menuEntriesAddress.addButton == 'Y') AppState().isArabic(context) ? Positioned( diff --git a/lib/ui/profile/delete_family_member.dart b/lib/ui/profile/delete_family_member.dart index d42c129..3b73512 100644 --- a/lib/ui/profile/delete_family_member.dart +++ b/lib/ui/profile/delete_family_member.dart @@ -88,8 +88,8 @@ class _DeleteFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = DateFormat('yyyy/MM/dd').format(dateValue); - datePar = DateFormat('yyyy/MM/dd hh:mm:ss').format(dateValue); + date = DateFormat('yyyy/MM/dd', "en_US").format(dateValue); + datePar = DateFormat('yyyy/MM/dd hh:mm:ss', "en_US").format(dateValue); setState(() {}); }, ).paddingOnly(bottom: 12), diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index 42f0758..aa0c931 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -227,6 +227,7 @@ class _DynamicInputScreenState extends State { (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.getEmployeeAddressList?.sEGMENTVALUEDSP ?? "", isReadOnly: model.rEADONLY == "Y", + length: model.mAXIMUMSIZE, onChange: (text) { model.getEmployeeAddressList?.sEGMENTVALUEDSP = text; }, @@ -242,10 +243,10 @@ class _DynamicInputScreenState extends State { DateTime date1 = DateTime(date.year, date.month, date.day); getAddressDffStructureList![index].dESCFLEXCONTEXTNAME = date.toString(); ESERVICESDV eservicesdv = ESERVICESDV( - pIDCOLUMNNAME: DateFormat('yyyy-MM-dd').format(date1), + pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1), pRETURNMSG: "null", pRETURNSTATUS: getAddressDffStructureList![index].dEFAULTVALUE, - pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); + pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s', "en_US").format(date)); getAddressDffStructureList![index].eSERVICESDV = eservicesdv; setState(() {}); if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) { @@ -270,8 +271,8 @@ class _DynamicInputScreenState extends State { // for date format type, date format is changed tempVar = e.eSERVICESDV?.pVALUECOLUMNNAME ?? ""; if (tempVar.isNotEmpty) { - DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('dd-MMM-yyy').format(date); + DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar); + tempVar = DateFormat('dd-MMM-yyy', "en_US").format(date); if (e.aPPLICATIONCOLUMNNAME == null) { effectiveDate = tempVar; } @@ -294,7 +295,7 @@ class _DynamicInputScreenState extends State { values, dynamicParams!.correctOrNew, countryCode, - effectiveDate.isEmpty ? DateFormat('dd-MMM-yyy').format(DateTime.now()) : effectiveDate, + effectiveDate.isEmpty ? DateFormat('dd-MMM-yyy', "en_US").format(DateTime.now()) : effectiveDate, ); Utils.hideLoading(context); diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart index 93a8eb3..2b00e4c 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart @@ -233,10 +233,10 @@ class _DynamicInputScreenState extends State { DateTime date1 = DateTime(date.year, date.month, date.day); getBasicDetDffStructureList![index].userBasicDetail!.sEGMENTVALUEDSP = date.toString(); ESERVICESDV eservicesdv = ESERVICESDV( - pIDCOLUMNNAME: DateFormat('yyyy-MM-dd').format(date1), + pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1), pRETURNMSG: "null", pRETURNSTATUS: getBasicDetDffStructureList![index].dEFAULTVALUE, - pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); + pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s', "en_US").format(date)); getBasicDetDffStructureList![index].eSERVICESDV = eservicesdv; setState(() {}); if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) { @@ -371,8 +371,8 @@ class _DynamicInputScreenState extends State { // for date format type, date format is changed tempVar = e.eSERVICESDV?.pVALUECOLUMNNAME ?? ""; if (tempVar.isNotEmpty) { - DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar); + tempVar = DateFormat('yyyy/MM/dd HH:mm:ss', "en_US").format(date); } } return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); diff --git a/lib/ui/profile/widgets/profile_info.dart b/lib/ui/profile/widgets/profile_info.dart index 73635d8..999b7cf 100644 --- a/lib/ui/profile/widgets/profile_info.dart +++ b/lib/ui/profile/widgets/profile_info.dart @@ -29,7 +29,7 @@ class ProfileInFo extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ 16.height, - memberInfo.eMPLOYEENAME!.toText22(), + memberInfo.eMPLOYEENAME!.toText22(isCentered: true), ("${memberInfo.eMPLOYEENUMBER!} | ${memberInfo.getPositionName()}").toText13(color: MyColors.grey80Color), memberInfo.eMPLOYEEEMAILADDRESS!.toText13(), 12.height, diff --git a/lib/ui/screens/my_requests/new_request.dart b/lib/ui/screens/my_requests/new_request.dart index 7a73497..3b138b8 100644 --- a/lib/ui/screens/my_requests/new_request.dart +++ b/lib/ui/screens/my_requests/new_request.dart @@ -176,6 +176,7 @@ class _NewRequestState extends State { model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, + length: model.mAXIMUMSIZE, onChange: (text) { model.fieldAnswer = text; model.eSERVICESDV ??= ESERVICESDV(); @@ -189,7 +190,7 @@ class _NewRequestState extends State { displayText = displayText.replaceAll(" 00:00:00", ""); } if (!displayText.contains("-")) { - displayText = DateFormat('yyyy-MM-dd').format(DateFormat("yyyy/MM/dd").parse(displayText)); + displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText)); } } return DynamicTextFieldWidget( @@ -200,7 +201,7 @@ class _NewRequestState extends State { onTap: () async { if ((getCCPDFFStructureModelList![index].eSERVICESDV?.pVALUECOLUMNNAME != null)) { if (getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS) { - selectedDate = DateFormat("yyyy/MM/dd").parse(getCCPDFFStructureModelList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", "")); + selectedDate = DateFormat("yyyy/MM/dd", "en_US").parse(getCCPDFFStructureModelList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", "")); } else { selectedDate = DateTime.parse(getCCPDFFStructureModelList![index].eSERVICESDV!.pVALUECOLUMNNAME!); } @@ -211,16 +212,16 @@ class _NewRequestState extends State { ESERVICESDV eservicesdv; if (getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS) { eservicesdv = ESERVICESDV( - pIDCOLUMNNAME: DateFormat('yyyy/MM/dd HH:MM:SS').format(date1), + pIDCOLUMNNAME: DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date1), pRETURNMSG: "null", pRETURNSTATUS: getCCPDFFStructureModelList![index].dEFAULTVALUE, - pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy/MM/dd HH:MM:SS').format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); + pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); } else { eservicesdv = ESERVICESDV( - pIDCOLUMNNAME: DateFormat('yyyy-MM-dd').format(date1), + pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1), pRETURNMSG: "null", pRETURNSTATUS: getCCPDFFStructureModelList![index].dEFAULTVALUE, - pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy-MM-dd hh:mm:ss').format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); + pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy-MM-dd hh:mm:ss', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); } getCCPDFFStructureModelList![index].eSERVICESDV = eservicesdv; setState(() {}); @@ -323,6 +324,7 @@ class _NewRequestState extends State { isPopup: true, isInputTypeNum: true, isReadOnly: model.rEADONLY == "Y", + length: model.mAXIMUMSIZE, ).paddingOnly(bottom: 12), itemBuilder: (_) => >[ for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem(child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), value: i), diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart index d980728..b4cb242 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart @@ -85,7 +85,7 @@ class _OffersAndDiscountsDetailsState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - getOffersList[0].discount!.toText16(isBold: true), + getOffersList[0].discountDescription!.toText16(isBold: true), InkWell( onTap: () { _shareOfferAsImage(); diff --git a/lib/ui/termination/end_employement.dart b/lib/ui/termination/end_employement.dart index cdfa46d..161532a 100644 --- a/lib/ui/termination/end_employement.dart +++ b/lib/ui/termination/end_employement.dart @@ -107,8 +107,8 @@ class _EndEmploymentScreenState extends State { tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; if (tempVar.isNotEmpty) { if (!tempVar.contains("/")) { - DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar); + tempVar = DateFormat('yyyy/MM/dd HH:mm:ss', "en_US").format(date); } } } @@ -303,6 +303,7 @@ class _EndEmploymentScreenState extends State { model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, + length: model.mAXIMUMSIZE, onChange: (text) { model.eSERVICESDV ??= ESERVICESDV(); model.eSERVICESDV!.pIDCOLUMNNAME = text; @@ -475,6 +476,7 @@ class _EndEmploymentScreenState extends State { (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.eSERVICESDV?.pIDCOLUMNNAME ?? "", isReadOnly: model.rEADONLY == "Y", + length: model.mAXIMUMSIZE, onChange: (text) { //model.fieldAnswer = text; }, diff --git a/lib/widgets/app_logo.dart b/lib/widgets/app_logo.dart index 3140c29..37c7997 100644 --- a/lib/widgets/app_logo.dart +++ b/lib/widgets/app_logo.dart @@ -13,7 +13,7 @@ class AppLogo extends StatelessWidget { return Row( children: [ SvgPicture.asset( - "assets/mohemm_logo.svg", + "assets/moe_logo.svg", height: 48, width: 48, alignment: Alignment.centerRight, diff --git a/lib/widgets/balances_dashboard_widget.dart b/lib/widgets/balances_dashboard_widget.dart index 8909dab..9c1fafe 100644 --- a/lib/widgets/balances_dashboard_widget.dart +++ b/lib/widgets/balances_dashboard_widget.dart @@ -63,7 +63,7 @@ class _BalancesDashboardWidgetState extends State { void changeAccrualDate(bool showLoading) async { try { if (showLoading) Utils.showLoading(context); - List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: widget.selectedEmp); + List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy", "en_US").format(accrualDateTime), empID: widget.selectedEmp); if (accrualList.isNotEmpty) { if (widget.isLeaveBalance) { leaveBalanceAccrual = accrualList[0]; diff --git a/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart b/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart index ec4146b..586681a 100644 --- a/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart +++ b/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; class DynamicTextFieldWidget extends StatelessWidget { final String labelText; @@ -17,11 +20,14 @@ class DynamicTextFieldWidget extends StatelessWidget { final bool isInputTypeNumSigned; final bool isObscureText; final bool isBackgroundEnable; + final int? length; + final String? toolTip; final void Function(String)? onChange; DynamicTextFieldWidget(this.labelText, this.hintText, //this.controller, {this.isObscureText = false, this.onTap, + this.onToolTipTap, this.suffixIconData, this.isEnable = true, this.isReadOnly = false, @@ -31,6 +37,8 @@ class DynamicTextFieldWidget extends StatelessWidget { this.onChange, this.isInputTypeNum = false, this.isInputTypeNumSigned = true, + this.length, + this.toolTip = "", this.isBackgroundEnable = false}); @override @@ -68,13 +76,18 @@ class DynamicTextFieldWidget extends StatelessWidget { enabled: isEnable, scrollPadding: EdgeInsets.zero, readOnly: isReadOnly, - keyboardType: (isInputTypeNum) ? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true)) : TextInputType.text, + keyboardType: (isInputTypeNum) + ? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true)) + : TextInputType.text, textInputAction: TextInputAction.done, //controller: controller, maxLines: lines, obscuringCharacter: "*", obscureText: isObscureText, onChanged: onChange, + inputFormatters: [ + LengthLimitingTextInputFormatter(length), + ], style: const TextStyle( fontSize: 14, height: 21 / 14, @@ -107,6 +120,10 @@ class DynamicTextFieldWidget extends StatelessWidget { ), if (isPopup) const Icon(Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor), if (onTap != null) Icon(suffixIconData ?? Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor), + if (toolTip!.isNotEmpty) + Icon(Icons.help_outline_rounded, color: MyColors.darkIconColor).onPress(() { + Utils.showToast(toolTip!); + }).paddingOnly(left: 6), ], ), ), diff --git a/lib/widgets/loading_dialog.dart b/lib/widgets/loading_dialog.dart index 9c88a39..4e71581 100644 --- a/lib/widgets/loading_dialog.dart +++ b/lib/widgets/loading_dialog.dart @@ -36,7 +36,7 @@ class _LoadingDialogState extends State { textDirection: TextDirection.rtl, child: Center( child: Image.asset( - "assets/images/logos/loading_mohemm_logo.gif", + "assets/images/logos/loading_moe.gif", height: 96.0, width: 96.0, ), diff --git a/lib/widgets/location/Location.dart b/lib/widgets/location/Location.dart index d407c1c..9329cb4 100644 --- a/lib/widgets/location/Location.dart +++ b/lib/widgets/location/Location.dart @@ -1,22 +1,11 @@ import 'dart:async'; -import 'dart:math'; -import 'dart:ui'; -import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:google_directions_api/google_directions_api.dart'; -import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:mohem_flutter_app/classes/app_permissions.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/theme/colors.dart'; -// import 'package:geodesy/geodesy.dart' as geodesy; -//Created By Mr.Zohaib class Location { - static _Map map = _Map(); - static void havePermission(Function(bool) callback) { Geolocator.checkPermission().then((value) async { if (value == LocationPermission.denied) { @@ -46,12 +35,11 @@ class Location { }); } - static void getCurrentLocation(Function(LatLng?, bool isMocked) callback, BuildContext context) { + static void getCurrentLocation(Function(Position position, bool isMocked) callback, BuildContext context) { void done(Position position) { //AppStorage.sp.saveLocation(position); bool isMocked = position.isMocked; - LatLng? myCurrentLocation = LatLng(position.latitude, position.longitude); - callback(myCurrentLocation, isMocked); + callback(position, isMocked); } AppPermissions.location((granted) { @@ -70,182 +58,4 @@ class Location { } }, context); } - - // static LatLng locationAwayFrom( - // {required LatLng loc1, num distanceMeters = 200.0, num bearing = 270.0}) { - // geodesy.LatLng l1 = geodesy.LatLng(loc1.latitude, loc1.longitude); - // geodesy.LatLng destinationPoint = geodesy.Geodesy() - // .destinationPointByDistanceAndBearing(l1, distanceMeters, bearing); - // return LatLng(destinationPoint.latitude, destinationPoint.longitude); - // } - - static Future distanceTo(LatLng destination) async { - var myLoc = await Geolocator.getLastKnownPosition(); - var distance = 0.0; - if (myLoc != null) { - distance = Geolocator.distanceBetween(destination.latitude, destination.longitude, myLoc.latitude, myLoc.longitude); - } - return distance; - } -} - -class _Map { - Marker createMarker( - String id, { - required LatLng coordinates, - BitmapDescriptor? icon, - VoidCallback? onTap, - }) { - MarkerId markerId = MarkerId(id); - return Marker( - icon: icon ?? BitmapDescriptor.defaultMarker, - markerId: markerId, - position: coordinates, - flat: false, - // infoWindow: InfoWindow(title: id, snippet: '*'), - onTap: onTap, - ); - } - - CameraPosition initialCamera({required Completer mapController, LatLng? position, double zoom = 12}) { - position = position ?? LatLng(24.7249303, 46.5416656); - CameraPosition riyadhEye = CameraPosition( - target: position, - zoom: zoom, - ); - mapController.future.then((controller) { - controller.animateCamera(CameraUpdate.newCameraPosition(riyadhEye)); - }); - return riyadhEye; - } - - CameraPosition moveTo(LatLng location, {double zoom = 12, double direction = 0.0, required Completer mapController, bool? animation}) { - var camera = CameraPosition(target: location, zoom: zoom, bearing: direction); - mapController.future.then((controller) { - animation ?? false ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera)); - }); - return camera; - } - - void moveCamera(CameraPosition camera, @required Completer mapController, bool animation) { - mapController.future.then((controller) { - animation ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera)); - }); - } - - void scrollBy({double x = 0, double y = 0, required Completer mapController, bool animation = true}) { - var camera = CameraUpdate.scrollBy(x, y); - mapController.future.then((controller) { - animation ? controller.animateCamera(camera) : controller.moveCamera(camera); - }); - } - - // void goToCurrentLocation({Completer? mapController, double? direction = 0.0, bool? animation}) { - // Location.getCurrentLocation((location) { - // moveTo(location!, zoom: 17, mapController: mapController!, animation: animation, direction: direction!); - // }); - // } - - var routes = Map(); - - void setRoutePolylines(LatLng? source, LatLng? destination, Set polylines, Completer mapController, Function(DirectionsRoute?) completion) { - if (source == null || destination == null) { - completion(null); - return; - } - - var origin = '${source.latitude},${source.longitude}'; - var destin = '${destination.latitude},${destination.longitude}'; - var routeId = '$origin->$destination'; - - void createPolyline(DirectionsRoute results) { - List polylineCoordinates = results.overviewPath!.map((e) => LatLng(e.latitude, e.longitude)).toList(); - PolylineId id = PolylineId("route"); - Polyline polyline = Polyline( - polylineId: id, - color: accentColor, - width: 5, - jointType: JointType.round, - startCap: Cap.roundCap, - endCap: Cap.roundCap, - points: polylineCoordinates, - ); - - polylines.removeWhere((element) => true); - polylines.add(polyline); - - LatLngBounds bound = getBounds(coordinates: polylineCoordinates); - focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: 100); - completion(routes[routeId]); - } - - var availableRoute = routes[routeId]; - if (availableRoute == null) { - var request = DirectionsRequest(origin: origin, destination: destin); - DirectionsService().route(request, (response, status) { - if (status == DirectionsStatus.ok && response.routes!.isNotEmpty) { - routes[routeId] = response.routes!.first; - createPolyline(response.routes!.first); - } - }); - } else { - createPolyline(availableRoute); - } - } - - LatLngBounds getBounds({required List coordinates}) { - var lngs = coordinates.map((c) => c.longitude).toList(); - var lats = coordinates.map((c) => c.latitude).toList(); - - double bottomMost = lngs.reduce(min); - double topMost = lngs.reduce(max); - double leftMost = lats.reduce(min); - double rightMost = lats.reduce(max); - - LatLngBounds bounds = LatLngBounds( - northeast: LatLng(rightMost, topMost), - southwest: LatLng(leftMost, bottomMost), - ); - return bounds; - - double? x0, x1, y0, y1; - for (LatLng latLng in coordinates) { - if (x0 == null) { - x0 = x1 = latLng.latitude; - y0 = y1 = latLng.longitude; - } else { - if (latLng.latitude > x1!) x1 = latLng.latitude; - if (latLng.latitude < x0) x0 = latLng.latitude; - if (latLng.longitude > y1!) y1 = latLng.longitude; - if (latLng.longitude < y0!) y0 = latLng.longitude; - } - } - return LatLngBounds(northeast: LatLng(x1!, y1!), southwest: LatLng(x0!, y0!)); - } - - void focusCameraToLatLngBounds({LatLngBounds? bound, Completer? mapController, double? padding}) async { - if (bound == null) return; - - CameraUpdate camera = CameraUpdate.newLatLngBounds(bound, padding!); - GoogleMapController controller = await mapController!.future; - controller.animateCamera(camera); - } - - void focusCameraTo2Points({LatLng? point1, LatLng? point2, Completer? mapController, double? padding}) async { - var source = point1; - var destination = point2; - if (source != null && destination != null) { - // 'package:google_maps_flutter_platform_interface/src/types/location.dart': Failed assertion: line 72 pos 16: 'southwest.latitude <= northeast.latitude': is not true. - LatLngBounds bound; - if (source.latitude <= destination.latitude) { - bound = LatLngBounds(southwest: source, northeast: destination); - } else { - bound = LatLngBounds(southwest: destination, northeast: source); - } - - if (bound == null) return; - - focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: padding); - } - } } diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 8603f6e..a4558b9 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:geolocator/geolocator.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'; @@ -95,11 +95,11 @@ class _MarkAttendanceWidgetState extends State { // if (isNfcEnabled) attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () { if (isNfcLocationEnabled) { - Location.getCurrentLocation((LatLng? latlng, bool isMocked) { + Location.getCurrentLocation((Position position, bool isMocked) { if (isMocked) { - markFakeAttendance("NFC", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? ""); + markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); } else { - performNfcAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); } }, context); } else { @@ -109,11 +109,11 @@ class _MarkAttendanceWidgetState extends State { if (isWifiEnabled) attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () { if (isWifiLocationEnabled) { - Location.getCurrentLocation((LatLng? latlng, bool isMocked) { + Location.getCurrentLocation((Position position, bool isMocked) { if (isMocked) { - markFakeAttendance("WIFI", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? ""); + markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); } else { - performWifiAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); } }, context); } else { @@ -124,11 +124,11 @@ class _MarkAttendanceWidgetState extends State { if (isQrEnabled) attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async { if (isQrLocationEnabled) { - Location.getCurrentLocation((LatLng? latlng, bool isMocked) { + Location.getCurrentLocation((Position position, bool isMocked) { if (isMocked) { - markFakeAttendance("QR", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? ""); + markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); } else { - performQrCodeAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); } }, context); } else { diff --git a/pubspec.yaml b/pubspec.yaml index f4c751a..1a8b0ff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ 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.0+300020 +version: 3.6.4+2 environment: sdk: ">=2.16.0 <3.0.0" @@ -46,7 +46,7 @@ dependencies: local_auth: ^1.1.9 fluttertoast: ^8.0.8 syncfusion_flutter_calendar: ^19.4.48 - flutter_calendar_carousel: ^2.1.0 +# flutter_calendar_carousel: ^2.1.0 pie_chart: ^5.1.0 shared_preferences: ^2.0.12 firebase_messaging: ^13.0.4 @@ -57,13 +57,7 @@ dependencies: uuid: ^3.0.6 image_picker: ^0.8.5+3 file_picker: ^4.6.1 - # maps - google_maps_flutter: ^2.0.2 - google_maps_utils: ^1.4.0+1 - google_directions_api: ^0.9.0 geolocator: ^9.0.2 - # flutter_compass: ^0.6.1 - google_maps_flutter_web: ^0.3.2 month_year_picker: ^0.2.0+1 month_picker_dialog_2: 0.5.5 open_file: ^3.2.1 @@ -71,7 +65,7 @@ dependencies: flutter_html: ^3.0.0-alpha.6 # flutter_barcode_scanner: ^2.0.0 qr_code_scanner: ^1.0.0 - 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 @@ -91,7 +85,7 @@ dependencies: logging: ^1.0.1 swipe_to: ^1.0.2 flutter_webrtc: ^0.9.16 - camera: ^0.10.0+4 + camera: ^0.10.3 flutter_local_notifications: any #firebase_analytics: any @@ -102,11 +96,16 @@ dependencies: #Encryption flutter_des: ^2.1.0 - video_player: ^2.4.7 + video_player: ^2.5.1 just_audio: ^0.9.30 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_push: ^6.7.0+300 + dependency_overrides: firebase_core_platform_interface: 4.5.1