# Conflicts:
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/app_state/app_state.dart
#	lib/generated/locale_keys.g.dart
pull/9/head
Sultan khan 3 years ago
commit fd6058e87d

@ -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"
}
}
]
}

@ -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
@ -51,7 +52,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "hmg.cloudSolutions.mohem"
minSdkVersion 21
minSdkVersion 28
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@ -66,8 +67,14 @@ android {
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

@ -7,12 +7,21 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Chat Web RTC Calling -->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="Mohemm"
android:extractNativeLibs="true"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round">
<activity

@ -3,12 +3,14 @@ buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.8'
classpath 'com.huawei.agconnect:agcp:1.8.0.300'
}
}
@ -16,6 +18,7 @@ allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
}
}

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path id="delete_1_" data-name="delete (1)" d="M13.657,2.343A8,8,0,0,0,2.343,13.657,8,8,0,0,0,13.657,2.343Zm-2.2,8.012a.781.781,0,1,1-1.1,1.1L8,9.1,5.645,11.46a.781.781,0,0,1-1.1-1.1L6.9,8,4.54,5.645a.781.781,0,0,1,1.1-1.1L8,6.9,10.355,4.54a.781.781,0,0,1,1.1,1.1L9.1,8Zm0,0" fill="#ca3332"/>
</svg>

After

Width:  |  Height:  |  Size: 386 B

@ -404,7 +404,8 @@
"stamp": "ختم",
"addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله",
"feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم",
"rateUI": ".1 كيف تريد تقييم التطبيق",
"rateUI": "كيف تريد أن تقيم",
"rateUI2": "ما مدى رضائك عن هذا التطبيق",
"submitSurvey": "ارسال الاستبيان",
"typeHere": "اكتب هنا",
"infoDetail": "تفاصيل المعلومات",
@ -424,7 +425,7 @@
"typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه",
"currentPassword": "كلمة المرور الحاليه",
"concurrentReports": "التقارير المتزامنه",
"EnterNewAddressMoved" : "أدخل عنوان جديد إذا كنت قد انتقلت",
"EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت",
"CorrectAddress": "تصحيح أو تعديل هذا العنوان",
"SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.",
"profile": {
@ -480,7 +481,7 @@
"gameTime": "وقت اللعب:",
"joinMarathon": "انضم إلى ماراثون",
"joinDemoMarathon": "انضم إلى الماراثون التجريبي",
"demo":"تجريبي",
"demo": "تجريبي",
"minutes": "الدقائق",
"seconds": "ثواني",
"note": "ملحوظة:",
@ -517,14 +518,22 @@
"startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة.",
"winners": "الفائزين!!!",
"expireAfter":"تنتهي بعد",
"oneWeek":"أسبوع 1",
"twoWeek":"2 أسبوع",
"expireAfter": "تنتهي بعد",
"oneWeek": "أسبوع 1",
"twoWeek": "2 أسبوع",
"noUpcoming": "لا يوجد قادم",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam" : "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض",
"group" : "مجموعة",
"searchGroup": "مجموعة البحث"
"searchGroup": "مجموعة البحث",
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"manage":"يدير",
"members":"أعضاء",
"areYouSureWantTodelete": "هل أنت متأكد من أنك تريد الحذف؟",
"groupMembers": "أعضاء المجموعة",
"manageGroup": "إدارة المجموعة",
"admin": "مسؤل"
}

@ -404,7 +404,8 @@
"stamp": "Stamp",
"addFavoriteList": "Do you want to add {name} in your favorite list",
"feedbackUserExperience": "This is to get the feedback about the user experience",
"rateUI": "1. How would you rate this UI?",
"rateUI": "How would you like to rate",
"rateUI2": "How do you satisfied with this application",
"submitSurvey": "Submit Survey",
"typeHere": "Type here",
"infoDetail": "Info Detail",
@ -526,5 +527,12 @@
"myTeam" : "My Team",
"youCanPlayDemo": "But you can play demo",
"group": "Groups",
"searchGroup": "Search Group"
"searchGroup": "Search Group",
"connectHmgWifi": "Connect HMG WIFI",
"manage": "Manage",
"members": "Members",
"areYouSureWantTodelete": "Are you sure want to delete?",
"groupMembers": "Group Members",
"manageGroup": "Manage Group",
"admin": "Admin"
}

File diff suppressed because one or more lines are too long

@ -144,7 +144,6 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
C4CFBC4C5CAC00182015ACD5 /* [CP] Embed Pods Frameworks */,
1C704830960BB41251F31356 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -204,23 +203,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
1C704830960BB41251F31356 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
2D06B7AD3B87C9C9059E4168 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;

@ -1,6 +1,7 @@
import UIKit
import Flutter
import Firebase
import flutter_local_notifications
@UIApplicationMain
@ -9,7 +10,13 @@ import Firebase
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
FirebaseApp.configure()
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

@ -2,6 +2,15 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsForMedia</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
@ -33,7 +42,7 @@
<key>NFCReaderUsageDescription</key>
<string>This App requires access to NFC to mark your attendance.</string>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to capture &amp; upload pictures.</string>
<string>This app requires camera access to capture &amp; upload picture as profile image.</string>
<key>NSFaceIDUsageDescription</key>
<string>This app requires Face ID to allow biometric authentication for app login.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
@ -46,15 +55,13 @@
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to for call.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@ -80,14 +87,9 @@
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>TAG</string>
</array>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>0000</string>
</array>
</dict>
</plist>

@ -87,13 +87,12 @@ class ApiClient {
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
var jsonData = jsonDecode(response.body);
if (jsonData["MessageStatus"] == 2) {
AppState().setIsAuthenticated = false;
if (jsonData["IsAuthenticated"] != null) {
AppState().setIsAuthenticated = jsonData["IsAuthenticated"];
}
if (jsonData["ErrorMessage"] == null && jsonData["MessageStatus"] == 1) {
if (jsonData["ErrorMessage"] == null) {
return factoryConstructor(jsonData);
} else {
APIError? apiError;

@ -12,10 +12,17 @@ import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/exceptions/api_exception.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart';
import 'package:mohem_flutter_app/models/chat/create_group_request.dart'
as createGroup;
import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' as groups;
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as user;
import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav;
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'
as groups;
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'
as user;
import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart'
as fav;
class ChatApiClient {
static final ChatApiClient _instance = ChatApiClient._internal();
@ -29,10 +36,14 @@ class ChatApiClient {
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatLoginTokenUrl}externaluserlogin",
{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"employeeNumber":
AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
"isMobile": true,
"deviceToken": AppState().getDeviceToken,
"deviceToken": AppState().getIsHuawei
? AppState().getHuaweiPushToken
: AppState().getDeviceToken,
"isHuaweiDevice": AppState().getIsHuawei,
},
);
@ -41,7 +52,10 @@ class ChatApiClient {
}
if (response.statusCode == 200) {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
} else if (response.statusCode == 501 || response.statusCode == 502 || response.statusCode == 503 || response.statusCode == 504) {
} else if (response.statusCode == 501 ||
response.statusCode == 502 ||
response.statusCode == 503 ||
response.statusCode == 504) {
getUserLoginToken();
} else {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
@ -50,9 +64,16 @@ class ChatApiClient {
return userLoginResponse;
}
Future<ChatUserModel> getChatMemberFromSearch(String searchParam, int cUserId, int pageNo) async {
Future<ChatUserModel> getChatMemberFromSearch(
String searchParam, int cUserId, int pageNo) async {
ChatUserModel chatUserModel;
Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync", {"employeeNumber": cUserId, "userName": searchParam, "pageNumber": pageNo},
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync",
{
"employeeNumber": cUserId,
"userName": searchParam,
"pageNumber": pageNo
},
token: AppState().chatDetails!.response!.token);
if (!kReleaseMode) {
logger.i("res: " + response.body);
@ -92,7 +113,12 @@ class ChatApiClient {
}
//Get User Chat History
Future<Response> getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async {
Future<Response> getSingleUserChatHistory(
{required int senderUID,
required int receiverUID,
required bool loadMore,
bool isNewChat = false,
required int paginationVal}) async {
try {
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal",
@ -103,23 +129,33 @@ class ChatApiClient {
}
return response;
} catch (e) {
getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
getSingleUserChatHistory(
senderUID: senderUID,
receiverUID: receiverUID,
loadMore: loadMore,
paginationVal: paginationVal);
throw e;
}
}
//Favorite Users
Future<fav.FavoriteChatUser> favUser({required int userID, required int targetUserID}) async {
Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatFavUser}addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
Future<fav.FavoriteChatUser> favUser(
{required int userID, required int targetUserID}) async {
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatFavUser}addFavUser",
{"targetUserId": targetUserID, "userId": userID},
token: AppState().chatDetails!.response!.token);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
fav.FavoriteChatUser favoriteChatUser =
fav.FavoriteChatUser.fromRawJson(response.body);
return favoriteChatUser;
}
//UnFavorite Users
Future<fav.FavoriteChatUser> unFavUser({required int userID, required int targetUserID}) async {
Future<fav.FavoriteChatUser> unFavUser(
{required int userID, required int targetUserID}) async {
try {
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatFavUser}deleteFavUser",
@ -129,7 +165,8 @@ class ChatApiClient {
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
fav.FavoriteChatUser favoriteChatUser =
fav.FavoriteChatUser.fromRawJson(response.body);
return favoriteChatUser;
} catch (e) {
e as APIException;
@ -144,10 +181,12 @@ class ChatApiClient {
print(AppState().chatDetails!.response!.token);
}
dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatMediaImageUploadUrl}upload'));
dynamic request = MultipartRequest(
'POST', Uri.parse('${ApiConsts.chatMediaImageUploadUrl}upload'));
request.fields.addAll({'userId': userId, 'fileSource': '1'});
request.files.add(await MultipartFile.fromPath('files', file.path));
request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
request.headers.addAll(
{'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
StreamedResponse response = await request.send();
String data = await response.stream.bytesToString();
if (!kReleaseMode) {
@ -157,7 +196,8 @@ class ChatApiClient {
}
// Download File For Chat
Future<Uint8List> downloadURL({required String fileName, required String fileTypeDescription}) async {
Future<Uint8List> downloadURL(
{required String fileName, required String fileTypeDescription}) async {
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatMediaImageUploadUrl}download",
{"fileType": fileTypeDescription, "fileName": fileName, "fileSource": 1},
@ -168,7 +208,8 @@ class ChatApiClient {
}
//Get Chat Users & Favorite Images
Future<List<ChatUserImageModel>> getUsersImages({required List<String> encryptedEmails}) async {
Future<List<ChatUserImageModel>> getUsersImages(
{required List<String> encryptedEmails}) async {
List<ChatUserImageModel> imagesData = [];
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatUserImages}images",
@ -201,11 +242,115 @@ class ChatApiClient {
}
return groups.GetUserGroups.fromRawJson(response.body);
} catch (e) {
//if fail api returning 500 hence just printing here
//if fail api returning 500 hence just printing here
print(e);
throw e;
}
}
Future<Response> deleteGroup(int? groupId) async {
try {
Response response = await ApiClient().postJsonForResponse(
ApiConsts.deleteGroup,
{"groupId":groupId},
token: AppState().chatDetails!.response!.token,
);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return response;
} catch (e) {
//if fail api returning 500 hence just printing here
print(e);
throw e;
}
}
Future<Response> updateGroupAdmin(
int? groupId, List<GroupUserList> groupList) async {
try {
Response response = await ApiClient().postJsonForResponse(
ApiConsts.updateGroupAdmin,
{"groupId": groupId, "groupUserList": groupList},
token: AppState().chatDetails!.response!.token,
);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return response;
} catch (e) {
//if fail api returning 500 hence just printing here
print(e);
throw e;
}
}
Future<List<GetGroupChatHistoryAsync>> getGroupChatHistory(
int? groupId, List<GroupUserList> groupList) async {
try {
Response response = await ApiClient().postJsonForResponse(
ApiConsts.getGroupChatHistoryAsync,
{
"groupId": groupId,
"targetUserList": groupList,
"CurrentId": AppState().chatDetails!.response!.id
},
token: AppState().chatDetails!.response!.token,
);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
List<GetGroupChatHistoryAsync> groupChat = [];
List groupChatData = json.decode(response.body);
for (var i in groupChatData) {
groupChat.add(GetGroupChatHistoryAsync.fromJson(i));
}
groupChat.sort((a, b) => b.createdDate!.compareTo(a.createdDate!));
return groupChat;
// for(GetGroupChatHistoryAsync i in groupChat) {
// return GetGroupChatHistoryAsync.fromJson(jsonEncode(i));
// }
} catch (e) {
//if fail api returning 500 hence just printing here
print(e);
throw e;
}
}
Future addGroupAndUsers(createGroup.CreateGroupRequest request) async {
try {
Response response = await ApiClient().postJsonForResponse(
ApiConsts.addGroupsAndUsers,
request,
token: AppState().chatDetails!.response!.token,
);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return response.body;
} catch (e) {
//if fail api returning 500 hence just printing here
print(e);
throw e;
}
}
Future updateGroupAndUsers(createGroup.CreateGroupRequest request) async {
try {
Response response = await ApiClient().postJsonForResponse(
ApiConsts.updateGroupsAndUsers,
request,
token: AppState().chatDetails!.response!.token,
);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return response.body;
} catch (e) {
//if fail api returning 500 hence just printing here
print(e);
throw e;
}
}
}

@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/models/dashboard/list_menu.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_main_response.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:platform_device_id/platform_device_id.dart';
import 'package:uuid/uuid.dart';
class DashboardApiClient {
@ -111,7 +112,8 @@ class DashboardApiClient {
// Generate a v4 (random) id
Map<String, dynamic> postParams = {
"UID": uuid.v4(), //Mobile Id
"UID": await PlatformDeviceId.getDeviceId, //uuid.v4(), //Mobile Id
// "UID": uuid.v4(), //Mobile Id
"Latitude": lat,
"Longitude": long,
"QRValue": QRValue,
@ -199,17 +201,18 @@ class DashboardApiClient {
}, url, postParams);
}
// Future setAdvertisementViewed(String masterID, int advertisementId) async {
// String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed";
//
// Map<String, dynamic> postParams = {
// "ItgNotificationMasterId": masterID,
// "ItgAdvertisement": {"advertisementId": advertisementId, "acknowledgment": true} //Mobile Id
// };
// postParams.addAll(AppState().postParamsJson);
// return await ApiClient().postJsonForObject((json) {
// // ItgMainRes responseData = ItgMainRes.fromJson(json);
// return json;
// }, url, postParams);
// }
Future setAdvertisementViewed(String masterID, int advertisementId) async {
String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed";
Map<String, dynamic> postParams = {
"ItgNotificationMasterId": masterID,
"EmployeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"ItgAdvertisement": {"advertisementId": advertisementId, "acknowledgment": true} //Mobile Id
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
// ItgMainRes responseData = ItgMainRes.fromJson(json);
return json;
}, url, postParams);
}
}

@ -34,6 +34,20 @@ class MarathonApiClient {
);
}
Future<int> getMarathonersCount({required String marathonId}) async {
Response response = await ApiClient().getJsonForResponse(
ApiConsts.marathonGetMarathonersCount + '?marathonId=$marathonId',
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
var json = jsonDecode(response.body);
logger.i("json in getMarathonersCount: $json");
MarathonGenericModel marathonGenericModel = MarathonGenericModel.fromJson(json);
return marathonGenericModel.data as int;
}
Future<String> getProjectId() async {
return await ApiClient().postJsonForObject(
(json) {
@ -73,8 +87,8 @@ class MarathonApiClient {
Future<int?> joinMarathonAsParticipant() async {
Map<String, String> jsonObject = <String, String>{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "",
"employeeNameAr": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
"employeeNameEn": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
"employeeNameAr": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
"employeeNameEn": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
"marathonId": AppState().getMarathonProjectId!,
};

@ -14,6 +14,7 @@ import 'package:mohem_flutter_app/models/get_mo_notification_body_list_model.dar
import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_model.dart';
@ -46,7 +47,7 @@ class WorkListApiClient {
Map<String, dynamic> postParams = {
"P_NOTIFICATION_TYPE": pNotificationType,
"P_PAGE_NUM": pPageNum,
"P_PAGE_LIMIT": 25,
"P_PAGE_LIMIT": 20,
"P_ITEM_TYPE": pItemType,
"P_SEARCH_FROM_USER": pSearchUser,
"P_SEARCH_ITEM_TYPE_DSP_NAME": pSearchItemType,
@ -413,7 +414,7 @@ class WorkListApiClient {
"EmployeeNumber": employeeNumber,
"Comments": "",
"AdditionalFields": null,
"NewUserEMPId":newUserEMPId
"NewUserEMPId": newUserEMPId
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
@ -589,7 +590,8 @@ class WorkListApiClient {
}, url, postParams);
}
Future<GenericResponseModel> submitComment({String? comment, String? email, String? userId, int? notificationId, required String apiMode, int? approverIndex = null}) async {
Future<GenericResponseModel> submitComment(
{String? comment, String? email, String? userId, int? notificationId, required String apiMode, int? approverIndex = null, List<Map<String, dynamic>>? attributeData = const []}) async {
String url = "${ApiConsts.erpRest}NOTIFICATION_ACTIONS";
Map<String, dynamic> postParams = {
"P_COMMENTS": comment,
@ -598,7 +600,7 @@ class WorkListApiClient {
"P_FORWARD_TO_USER_NAME": userId,
"P_NOTIFICATION_ID": notificationId,
"P_APPROVER_INDEX": approverIndex,
"RespondAttributeList": []
"RespondAttributeList": attributeData
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
@ -626,4 +628,18 @@ class WorkListApiClient {
return responseData.updateUserItemTypesList;
}, url, postParams);
}
Future<GetPRInformationList?> getPRDetailsForPO(String poLineID) async {
String url = "${ApiConsts.erpRest}GET_PR_INFORMATION";
Map<String, dynamic> postParams = {
"P_PO_LINE_ID": poLineID,
"P_PAGE_LIMIT": 100,
"P_PAGE_NUM": 1,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getPRInformationList;
}, url, postParams);
}
}

@ -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';
@ -46,6 +45,8 @@ class AppState {
String? get getForgetPasswordTokenID => forgetPasswordTokenID;
bool isConnectedToHMG = false;
//Wifi info
String? _mohemmWifiSSID;
@ -77,7 +78,19 @@ class AppState {
bool get getIsDemoMarathon => _isDemoMarathon;
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.2, 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.6, mobileType: Platform.isAndroid ? "android" : "ios");
void setPostParamsInitConfig() {
isAuthenticated = false;

@ -21,7 +21,11 @@ class ApiConsts {
//Groups
static String getGroupByUserId = chatServerBaseApiUrl + "group/getgroupsbyuserid/";
static String deleteGroup = chatServerBaseApiUrl + "group/updateGroupIsDeleted/";
static String updateGroupAdmin = chatServerBaseApiUrl + "group/updateGroupAdmin/";
static String getGroupChatHistoryAsync = chatServerBaseApiUrl + "GroupChat/GetGroupChatHistoryAsync/";
static String addGroupsAndUsers = chatServerBaseApiUrl + "group/addgroupandusers/";
static String updateGroupsAndUsers = chatServerBaseApiUrl + "group/updategroupandusers/";
// static String chatSearchMember = chatLoginTokenUrl + "user/";
static String chatRecentUrl = chatServerBaseApiUrl + "UserChatHistory/"; //For a Mem
@ -41,6 +45,7 @@ class ApiConsts {
static String marathonSubmitAnswerUrl = marathonBaseUrl + "question/submit";
static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/";
static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/";
static String marathonGetMarathonersCount = marathonBaseUrl + "Participant/GetRemainingParticipants";
//DummyCards for the UI
static CardContent dummyQuestion = const CardContent();

@ -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) {

@ -9,4 +9,5 @@ class MyLottieConsts {
static const String congratsGif = "assets/images/congrats.gif";
static const String loadingLottie = "assets/lottie/loading_lottie.json";
static const String noWinnerLottie = "assets/lottie/no_winner.json";
static const String audioPlaybackLottie = "assets/lottie/audio_playback.json";
}

@ -0,0 +1,21 @@
import 'package:flutter/foundation.dart';
import 'package:just_audio/just_audio.dart';
class MyCustomStream extends StreamAudioSource {
final Uint8List bytes;
MyCustomStream(this.bytes);
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= bytes.length;
return StreamAudioResponse(
sourceLength: bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(bytes.sublist(start, end)),
contentType: 'audio/aac',
);
}
}

@ -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<void> requestPermissions() async {
if (Platform.isIOS) {
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
@ -35,6 +40,10 @@ class AppNotifications {
}
void init(String? firebaseToken) async {
// if (Platform.isAndroid) {
// hmsApiAvailability = HmsApiAvailability();
// }
await requestPermissions();
AppState().setDeviceToken = firebaseToken;
await Permission.notification.isDenied.then((bool value) {
@ -57,10 +66,53 @@ class AppNotifications {
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
AppState().setDeviceToken = token;
});
if (Platform.isAndroid) {
// await hmsApiAvailability.isHMSAvailable().then((value) async {
if (!(await Utils.isGoogleServicesAvailable())) {
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<void> 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) {
Utils.saveStringFromPrefs("isAppOpendByChat", "true");
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
}
void _handleOpenApp(RemoteMessage message) {
@ -77,7 +129,6 @@ AndroidNotificationChannel channel = const AndroidNotificationChannel(
Future<dynamic> backgroundMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
Utils.saveStringFromPrefs("isAppOpendByChat", "true");
logger.w(message.data["user_chat_history_response"]);
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
}

@ -7,6 +7,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/config/routes.dart';
@ -115,12 +116,14 @@ class Utils {
} else {
if (!AppState().isAuthenticated) {
showDialog(
barrierDismissible: false,
context: cxt,
builder: (cxt) => ConfirmDialog(
message: errorMessage,
onTap: () {
Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route<dynamic> route) => false);
},
onCloseTap: () {},
),
);
} else {
@ -264,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) {
@ -334,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));
}
@ -388,4 +391,14 @@ class Utils {
print(err);
});
}
//HUAWEI DECISION MAKING
static Future<bool> isGoogleServicesAvailable() async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
String status = availability.toString().split('.').last;
if (status == "success") {
return true;
}
return false;
}
}

@ -7,6 +7,9 @@ import 'package:mohem_flutter_app/ui/bottom_sheets/attendence_details_bottom_she
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_home.dart';
import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_members.dart';
import 'package:mohem_flutter_app/ui/chat/manage_group.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart';
import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart';
@ -183,6 +186,10 @@ class AppRoutes {
static const String chatDetailed = "/chatDetailed";
static const String chatFavoriteUsers = "/chatFavoriteUsers";
//Group Chat
static const String manageGroup = "/manageGroup";
static const String groupMembers = "/groupmembers";
static const String groupChatDetailed = "/groupChatDetailed";
//Marathon
static const String marathonIntroScreen = "/marathonIntroScreen";
static const String marathonScreen = "/marathonScreen";
@ -295,6 +302,11 @@ class AppRoutes {
chatDetailed: (BuildContext context) => ChatDetailScreen(),
chatFavoriteUsers: (BuildContext context) => ChatFavoriteUsersScreen(),
//Group Chat
manageGroup: (BuildContext context) => ManageGroupScreen(),
groupMembers: (BuildContext context) => GroupMembersScreen(),
groupChatDetailed: (BuildContext context) => GroupChatDetailScreen(),
// Marathon
marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(),
marathonScreen: (BuildContext context) => MarathonScreen(),

@ -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<String> otpFieldClear = ValueNotifier<String>("");

@ -22,6 +22,17 @@ extension TrimString on String {
}
}
String displayLocalizedContent({required bool isPhoneLangArabic, required int selectedLanguage, required String englishContent, required String arabicContent}) {
if (selectedLanguage == 1) {
return englishContent;
} else if (selectedLanguage == 2) {
return arabicContent;
} else if (selectedLanguage == 3) {
return isPhoneLangArabic ? arabicContent : englishContent;
}
return englishContent;
}
extension EmailValidator on String {
Widget get toWidget => Text(this);
@ -111,9 +122,10 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null),
);
Widget toText16({Color? color, bool isUnderLine = false, bool isBold = false, int? maxlines, double? height}) => Text(
Widget toText16({Color? color, bool isUnderLine = false, bool isBold = false, int? maxlines, double? height, bool isCentered = false}) => Text(
this,
maxLines: maxlines,
textAlign: isCentered ? TextAlign.center : null,
style: TextStyle(
color: color ?? MyColors.darkTextColor,
fontSize: 16,
@ -158,13 +170,15 @@ extension EmailValidator on String {
style: TextStyle(height: 1, color: color ?? MyColors.darkTextColor, fontSize: 22, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
);
Widget toText24({Color? color, bool isBold = false}) => Text(
Widget toText24({Color? color, bool isBold = false, bool isCentered = false}) => Text(
this,
textAlign: isCentered ? TextAlign.center : null,
style: TextStyle(height: 23 / 24, color: color ?? MyColors.darkTextColor, fontSize: 24, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
);
Widget toText30({Color? color, bool isBold = false}) => Text(
Widget toText30({Color? color, bool isBold = false, bool isCentered = false}) => Text(
this,
textAlign: isCentered ? TextAlign.center : null,
style: TextStyle(height: 20 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.2, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
);
@ -219,7 +233,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) {

@ -420,7 +420,8 @@ class CodegenLoader extends AssetLoader{
"stamp": "ختم",
"addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله",
"feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم",
"rateUI": ".1 كيف تريد تقييم التطبيق",
"rateUI": "كيف تريد أن تقيم",
"rateUI2": "ما مدى رضائك عن هذا التطبيق",
"submitSurvey": "ارسال الاستبيان",
"typeHere": "اكتب هنا",
"infoDetail": "تفاصيل المعلومات",
@ -533,11 +534,18 @@ class CodegenLoader extends AssetLoader{
"startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة.",
"winners": "الفائزين!!!",
"expireAfter": "تنتهي بعد",
"oneWeek": "أسبوع 1",
"twoWeek": "2 أسبوع",
"noUpcoming": "لا يوجد قادم",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam": "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض"
"youCanPlayDemo": "لكن يمكنك لعب العرض",
"group": "مجموعة",
"searchGroup": "مجموعة البحث",
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI"
};
static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm",
@ -945,7 +953,8 @@ static const Map<String,dynamic> en_US = {
"stamp": "Stamp",
"addFavoriteList": "Do you want to add {name} in your favorite list",
"feedbackUserExperience": "This is to get the feedback about the user experience",
"rateUI": "1. How would you rate this UI?",
"rateUI": "How would you like to rate",
"rateUI2": "How do you satisfied with this application",
"submitSurvey": "Submit Survey",
"typeHere": "Type here",
"infoDetail": "Info Detail",
@ -1058,11 +1067,17 @@ static const Map<String,dynamic> en_US = {
"startingIn": "Starting in",
"youAreOutOfContest": "You are out of the contest.",
"winners": "WINNERS!!!",
"expireAfter": "Expires After",
"oneWeek": "1 Week",
"twoWeek": "2 Week",
"noUpcoming": "There is no upcoming",
"fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.",
"noWinner": "Sad! No one won today.",
"myTeam": "My Team",
"youCanPlayDemo": "But you can play demo"
"youCanPlayDemo": "But you can play demo",
"group": "Groups",
"searchGroup": "Search Group",
"connectHmgWifi": "Connect HMG WIFI"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -1,6 +1,6 @@
// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart
abstract class LocaleKeys {
abstract class LocaleKeys {
static const mohemm = 'mohemm';
static const english = 'english';
static const arabic = 'arabic';
@ -250,7 +250,7 @@ abstract class LocaleKeys {
static const Payroll = 'Payroll';
static const civilIdentityNumber = 'civilIdentityNumber';
static const dateOfBirth = 'dateOfBirth';
static const maritalStatus = 'maritalStatus ';
static const maritalStatus = 'maritalStatus ';
static const fullName = 'fullName';
static const remove = 'remove';
static const submit = 'submit';
@ -280,7 +280,7 @@ abstract class LocaleKeys {
static const enterNewInfo = 'enterNewInfo';
static const endDate = 'endDate';
static const removeThisMember = 'removeThisMember';
static const wantUpdateThisMember = 'wantUpdateThisMember ';
static const wantUpdateThisMember = 'wantUpdateThisMember ';
static const addNewFamilyMember = 'addNewFamilyMember';
static const addRow = 'addRow';
static const pleaseSelect = 'pleaseSelect';
@ -406,6 +406,7 @@ abstract class LocaleKeys {
static const addFavoriteList = 'addFavoriteList';
static const feedbackUserExperience = 'feedbackUserExperience';
static const rateUI = 'rateUI';
static const rateUI2 = 'rateUI2';
static const submitSurvey = 'submitSurvey';
static const typeHere = 'typeHere';
static const infoDetail = 'infoDetail';
@ -503,14 +504,22 @@ abstract class LocaleKeys {
static const startingIn = 'startingIn';
static const youAreOutOfContest = 'youAreOutOfContest';
static const winners = 'winners';
static const noUpcoming = 'noUpcoming';
static const fakeLocation = 'fakeLocation';
static const expireAfter = 'expireAfter';
static const oneWeek = 'oneWeek';
static const twoWeek = 'twoWeek';
static const noUpcoming = 'noUpcoming';
static const fakeLocation = 'fakeLocation';
static const noWinner = 'noWinner';
static const myTeam = 'myTeam';
static const youCanPlayDemo = 'youCanPlayDemo';
static const group = 'group';
static const searchGroup = 'searchGroup';
static const connectHmgWifi = 'connectHmgWifi';
static const connectedHmgWifi = 'connectedHmgWifi';
static const manage = 'manage';
static const members = 'members';
static const areYouSureWantTodelete = 'areYouSureWantTodelete';
static const groupMembers = "groupMembers";
static const manageGroup = "manageGroup";
static const admin = "admin";
}

@ -9,6 +9,7 @@ import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/generated/codegen_loader.g.dart';
import 'package:mohem_flutter_app/models/post_params_model.dart';
import 'package:mohem_flutter_app/provider/chat_call_provider.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/provider/eit_provider_model.dart';
@ -27,7 +28,6 @@ Logger logger = Logger(
// output: null, // U
);
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
@ -69,7 +69,10 @@ Future<void> main() async {
),
ChangeNotifierProvider<MarathonProvider>(
create: (_) => MarathonProvider(),
)
),
// ChangeNotifierProvider<ChatCallProvider>(
// create: (_) => ChatCallProvider(),
// ),
],
child: const MyApp(),
),
@ -261,4 +264,3 @@ class MyApp extends StatelessWidget {
// });
// }
// }

@ -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>? 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<String, dynamic> 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<UserChatHistoryLineRequestList>.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<String, dynamic> 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<String, dynamic> json) => CallerDetails(
response: json["response"] == null ? null : Response.fromJson(json["response"]),
errorResponses: json["errorResponses"],
);
Map<String, dynamic> 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<dynamic>.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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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,
};
}

@ -0,0 +1,159 @@
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
class CreateGroupRequest {
String? groupName;
int? adminUserId;
List<ChatUser>? groupUserList;
bool? canAttach;
bool? canAudioC;
bool? canShareS;
bool? canVideoC;
bool? isMeeting;
bool? canArchive;
int? groupId;
CreateGroupRequest(
{this.groupName,
this.adminUserId,
this.groupUserList,
this.canAttach,
this.canAudioC,
this.canShareS,
this.canVideoC,
this.isMeeting,
this.canArchive,
this.groupId
});
CreateGroupRequest.fromJson(Map<String, dynamic> json) {
groupName = json['groupName'];
adminUserId = json['adminUserId'];
if (json['groupUserList'] != null) {
groupUserList = <ChatUser>[];
json['groupUserList'].forEach((v) {
groupUserList!.add(new ChatUser.fromJson(v));
});
}
canAttach = json['canAttach'];
canAudioC = json['canAudioC'];
canShareS = json['canShareS'];
canVideoC = json['canVideoC'];
isMeeting = json['isMeeting'];
canArchive = json['canArchive'];
groupId = json['groupId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['groupName'] = this.groupName;
data['adminUserId'] = this.adminUserId;
if (this.groupUserList != null) {
data['groupUserList'] =
this.groupUserList!.map((v) => v.toJson()).toList();
}
data['canAttach'] = this.canAttach;
data['canAudioC'] = this.canAudioC;
data['canShareS'] = this.canShareS;
data['canVideoC'] = this.canVideoC;
data['isMeeting'] = this.isMeeting;
data['canArchive'] = this.canArchive;
data['groupId'] = this.groupId;
return data;
}
}
class GroupUserList {
int? id;
String? userName;
String? email;
dynamic? phone;
String? title;
int? userStatus;
String? image;
int? unreadMessageCount;
int? userAction;
bool? isPin;
bool? isFav;
bool? isAdmin;
Null? rKey;
int? totalCount;
bool? isHuaweiDevice;
Null? deviceToken;
String? token;
bool? isDomainUser;
bool? isActiveCode;
String? encryptedUserId;
String? encryptedUserName;
GroupUserList(
{this.id,
this.userName,
this.email,
this.phone,
this.title,
this.userStatus,
this.image,
this.unreadMessageCount,
this.userAction,
this.isPin,
this.isFav,
this.isAdmin,
this.rKey,
this.totalCount,
this.isHuaweiDevice,
this.deviceToken,
this.token,
this.isDomainUser,
this.isActiveCode,
this.encryptedUserId,
this.encryptedUserName});
GroupUserList.fromJson(Map<String, dynamic> json) {
id = json['id'];
userName = json['userName'];
email = json['email'];
phone = json['phone'];
title = json['title'];
userStatus = json['userStatus'];
image = json['image'];
unreadMessageCount = json['unreadMessageCount'];
userAction = json['userAction'];
isPin = json['isPin'];
isFav = json['isFav'];
isAdmin = json['isAdmin'];
rKey = json['rKey'];
totalCount = json['totalCount'];
isHuaweiDevice = json['isHuaweiDevice'];
deviceToken = json['deviceToken'];
token = json['token'];
isDomainUser = json['isDomainUser'];
isActiveCode = json['isActiveCode'];
encryptedUserId = json['encryptedUserId'];
encryptedUserName = json['encryptedUserName'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['userName'] = this.userName;
data['email'] = this.email;
data['phone'] = this.phone;
data['title'] = this.title;
data['userStatus'] = this.userStatus;
data['image'] = this.image;
data['unreadMessageCount'] = this.unreadMessageCount;
data['userAction'] = this.userAction;
data['isPin'] = this.isPin;
data['isFav'] = this.isFav;
data['isAdmin'] = this.isAdmin;
data['rKey'] = this.rKey;
data['totalCount'] = this.totalCount;
data['isHuaweiDevice'] = this.isHuaweiDevice;
data['deviceToken'] = this.deviceToken;
data['token'] = this.token;
data['isDomainUser'] = this.isDomainUser;
data['isActiveCode'] = this.isActiveCode;
data['encryptedUserId'] = this.encryptedUserId;
data['encryptedUserName'] = this.encryptedUserName;
return data;
}
}

@ -0,0 +1,264 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:just_audio/just_audio.dart';
class GetGroupChatHistoryAsync {
int? groupChatHistoryId;
String? contant;
String? contantNo;
int? chatEventId;
dynamic? fileTypeId;
bool? isSeen;
bool? isDelivered;
String? createdDate;
int? chatSource;
int? currentUserId;
String? currentUserName;
int? groupId;
String? groupName;
dynamic? encryptedGroupId;
dynamic? encryptedGroupName;
dynamic? callStatus;
String? conversationId;
List<GroupChatHistoryTargetUserList>? groupChatHistoryTargetUserList;
FileTypeResponse? fileTypeResponse;
GroupChatReplyResponse? groupChatReplyResponse;
bool? isReplied;
bool? isImageLoaded;
Uint8List? image;
File? voice;
AudioPlayer? voiceController;
GetGroupChatHistoryAsync(
{this.groupChatHistoryId,
this.contant,
this.contantNo,
this.chatEventId,
this.fileTypeId,
this.isSeen,
this.isDelivered,
this.createdDate,
this.chatSource,
this.currentUserId,
this.currentUserName,
this.groupId,
this.groupName,
this.encryptedGroupId,
this.encryptedGroupName,
this.callStatus,
this.conversationId,
this.groupChatHistoryTargetUserList,
this.fileTypeResponse,
this.groupChatReplyResponse,
this.image,
this.isImageLoaded,
this.isReplied,
this.voice,
this.voiceController
});
GetGroupChatHistoryAsync.fromJson(Map<String, dynamic> json) {
groupChatHistoryId = json['groupChatHistoryId'];
contant = json['contant'];
contantNo = json['contantNo'];
chatEventId = json['chatEventId'];
fileTypeId = json['fileTypeId'];
isSeen = json['isSeen'];
isDelivered = json['isDelivered'];
createdDate = json['createdDate'];
chatSource = json['chatSource'];
currentUserId = json['currentUserId'];
currentUserName = json['currentUserName'];
groupId = json['groupId'];
groupName = json['groupName'];
encryptedGroupId = json['encryptedGroupId'];
encryptedGroupName = json['encryptedGroupName'];
callStatus = json['callStatus'];
conversationId = json['conversationId'];
if (json['groupChatHistoryTargetUserList'] != null) {
groupChatHistoryTargetUserList = <GroupChatHistoryTargetUserList>[];
json['groupChatHistoryTargetUserList'].forEach((v) {
groupChatHistoryTargetUserList!
.add(new GroupChatHistoryTargetUserList.fromJson(v));
});
}
fileTypeResponse = json['fileTypeResponse'] != null
? new FileTypeResponse.fromJson(json['fileTypeResponse'])
: null;
groupChatReplyResponse = json["userChatReplyResponse"] == null ? null : GroupChatReplyResponse.fromJson(json["userChatReplyResponse"]);
isReplied= json['isReplied'];
isImageLoaded= json['isImageLoaded'];
image= json['image'];
voice= json['voice'];
voiceController = json["fileTypeId"] == 13 ? AudioPlayer() : null;
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['groupChatHistoryId'] = this.groupChatHistoryId;
data['contant'] = this.contant;
data['contantNo'] = this.contantNo;
data['chatEventId'] = this.chatEventId;
data['fileTypeId'] = this.fileTypeId;
data['isSeen'] = this.isSeen;
data['isDelivered'] = this.isDelivered;
data['createdDate'] = this.createdDate;
data['chatSource'] = this.chatSource;
data['currentUserId'] = this.currentUserId;
data['currentUserName'] = this.currentUserName;
data['groupId'] = this.groupId;
data['groupName'] = this.groupName;
data['encryptedGroupId'] = this.encryptedGroupId;
data['encryptedGroupName'] = this.encryptedGroupName;
data['callStatus'] = this.callStatus;
data['conversationId'] = this.conversationId;
if (this.groupChatHistoryTargetUserList != null) {
data['groupChatHistoryTargetUserList'] =
this.groupChatHistoryTargetUserList!.map((v) => v.toJson()).toList();
}
if (this.fileTypeResponse != null) {
data['fileTypeResponse'] = this.fileTypeResponse!.toJson();
}
if(this.groupChatReplyResponse !=null) {
data['groupChatReplyResponse'] = this.groupChatReplyResponse;
}
data['isReplied'] =isReplied;
data['isImageLoaded'] = isImageLoaded;
data['image'] = image;
data['voice'] = voice;
data["fileTypeId"] == 13 ? AudioPlayer() : null;
return data;
}
}
class GroupChatHistoryTargetUserList {
int? groupChatHistoryLineId;
bool? isSeen;
bool? isDelivered;
int? targetUserId;
String? targetUserName;
Null? userAction;
GroupChatHistoryTargetUserList(
{this.groupChatHistoryLineId,
this.isSeen,
this.isDelivered,
this.targetUserId,
this.targetUserName,
this.userAction});
GroupChatHistoryTargetUserList.fromJson(Map<String, dynamic> json) {
groupChatHistoryLineId = json['groupChatHistoryLineId'];
isSeen = json['isSeen'];
isDelivered = json['isDelivered'];
targetUserId = json['targetUserId'];
targetUserName = json['targetUserName'];
userAction = json['userAction'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['groupChatHistoryLineId'] = this.groupChatHistoryLineId;
data['isSeen'] = this.isSeen;
data['isDelivered'] = this.isDelivered;
data['targetUserId'] = this.targetUserId;
data['targetUserName'] = this.targetUserName;
data['userAction'] = this.userAction;
return data;
}
}
class FileTypeResponse {
int? fileTypeId;
dynamic? fileTypeName;
dynamic? fileTypeDescription;
dynamic? fileKind;
dynamic? fileName;
FileTypeResponse(
{this.fileTypeId,
this.fileTypeName,
this.fileTypeDescription,
this.fileKind,
this.fileName});
FileTypeResponse.fromJson(Map<String, dynamic> json) {
fileTypeId = json['fileTypeId'];
fileTypeName = json['fileTypeName'];
fileTypeDescription = json['fileTypeDescription'];
fileKind = json['fileKind'];
fileName = json['fileName'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['fileTypeId'] = this.fileTypeId;
data['fileTypeName'] = this.fileTypeName;
data['fileTypeDescription'] = this.fileTypeDescription;
data['fileKind'] = this.fileKind;
data['fileName'] = this.fileName;
return data;
}
}
class GroupChatReplyResponse {
GroupChatReplyResponse(
{this.userChatHistoryId,
this.chatEventId,
this.contant,
this.contantNo,
this.fileTypeId,
this.createdDate,
this.targetUserId,
this.targetUserName,
this.fileTypeResponse,
this.isImageLoaded,
this.image,
this.voice});
int? userChatHistoryId;
int? chatEventId;
String? contant;
String? contantNo;
dynamic? fileTypeId;
DateTime? createdDate;
int? targetUserId;
String? targetUserName;
FileTypeResponse? fileTypeResponse;
bool? isImageLoaded;
Uint8List? image;
Uint8List? voice;
factory GroupChatReplyResponse.fromJson(Map<String, dynamic> json) => GroupChatReplyResponse(
userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"],
chatEventId: json["chatEventId"] == null ? null : json["chatEventId"],
contant: json["contant"] == null ? null : json["contant"],
contantNo: json["contantNo"] == null ? null : json["contantNo"],
fileTypeId: json["fileTypeId"],
createdDate: json["createdDate"] == null ? null : DateTime.parse(json["createdDate"]),
targetUserId: json["targetUserId"] == null ? null : json["targetUserId"],
targetUserName: json["targetUserName"] == null ? null : json["targetUserName"],
fileTypeResponse: json["fileTypeResponse"] == null ? null : FileTypeResponse.fromJson(json["fileTypeResponse"]),
isImageLoaded: false,
image: null,
voice: null,
);
Map<String, dynamic> toJson() => {
"userChatHistoryId": userChatHistoryId == null ? null : userChatHistoryId,
"chatEventId": chatEventId == null ? null : chatEventId,
"contant": contant == null ? null : contant,
"contantNo": contantNo == null ? null : contantNo,
"fileTypeId": fileTypeId,
"createdDate": createdDate == null ? null : createdDate!.toIso8601String(),
"targetUserId": targetUserId == null ? null : targetUserId,
"targetUserName": targetUserName == null ? null : targetUserName,
"fileTypeResponse": fileTypeResponse == null ? null : fileTypeResponse!.toJson(),
};
}

@ -69,6 +69,7 @@ class ChatUser {
this.isImageLoaded,
this.isImageLoading,
this.userLocalDownlaodedImage,
this.isChecked
});
int? id;
@ -89,7 +90,7 @@ class ChatUser {
bool? isImageLoaded;
bool? isImageLoading;
File? userLocalDownlaodedImage;
bool? isChecked;
factory ChatUser.fromRawJson(String str) => ChatUser.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
@ -112,7 +113,9 @@ class ChatUser {
isTyping: false,
isImageLoaded: false,
isImageLoading: true,
userLocalDownlaodedImage: null);
userLocalDownlaodedImage: null,
isChecked: false
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
@ -129,5 +132,6 @@ class ChatUser {
"isAdmin": isAdmin == null ? null : isAdmin,
"rKey": rKey,
"totalCount": totalCount == null ? null : totalCount,
"isChecked":isChecked
};
}

@ -1,18 +1,19 @@
import 'dart:convert';
class GetUserGroups {
List<Response>? response;
List<GroupResponse>? groupresponse;
Null? errorResponses;
GetUserGroups({this.response, this.errorResponses});
GetUserGroups({this.groupresponse, this.errorResponses});
factory GetUserGroups.fromRawJson(String str) => GetUserGroups.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
GetUserGroups.fromJson(Map<String, dynamic> json) {
if (json['response'] != null) {
response = <Response>[];
groupresponse = <GroupResponse>[];
json['response'].forEach((v) {
response!.add(new Response.fromJson(v));
if(v['isDeleted'] == false)
groupresponse!.add(new GroupResponse.fromJson(v));
});
}
errorResponses = json['errorResponses'];
@ -20,15 +21,15 @@ class GetUserGroups {
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
if (this.response != null) {
data['response'] = this.response!.map((v) => v.toJson()).toList();
if (this.groupresponse != null) {
data['response'] = this.groupresponse!.map((v) => v.toJson()).toList();
}
data['errorResponses'] = this.errorResponses;
return data;
}
}
class Response {
class GroupResponse {
int? groupId;
String? groupName;
Null? groupIcon;
@ -47,7 +48,7 @@ class Response {
AdminUser? adminUser;
List<GroupUserList>? groupUserList;
Response(
GroupResponse(
{this.groupId,
this.groupName,
this.groupIcon,
@ -66,7 +67,7 @@ class Response {
this.adminUser,
this.groupUserList});
Response.fromJson(Map<String, dynamic> json) {
GroupResponse.fromJson(Map<String, dynamic> json) {
groupId = json['groupId'];
groupName = json['groupName'];
groupIcon = json['groupIcon'];

@ -28,6 +28,7 @@ import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart';
import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/models/get_schedule_shifts_details_list_model.dart';
@ -226,6 +227,7 @@ class GenericResponseModel {
List<GetPoItemHistoryList>? getPoItemHistoryList;
GetPoNotificationBodyList? getPoNotificationBodyList;
GetPrNotificationBodyList? getPrNotificationBodyList;
GetPRInformationList? getPRInformationList;
List<GetQuotationAnalysisList>? getQuotationAnalysisList;
List<GetRFCEmployeeList>? getRFCEmployeeListList;
List<String>? getRespondAttributeValueList;
@ -490,6 +492,7 @@ class GenericResponseModel {
this.getPoItemHistoryList,
this.getPoNotificationBodyList,
this.getPrNotificationBodyList,
this.getPRInformationList,
this.getQuotationAnalysisList,
this.getRFCEmployeeListList,
this.getRespondAttributeValueList,
@ -979,6 +982,7 @@ class GenericResponseModel {
}
getPoNotificationBodyList = json['GetPoNotificationBodyList'] != null ? GetPoNotificationBodyList.fromJson(json['GetPoNotificationBodyList']) : null;
getPrNotificationBodyList = json['GetPrNotificationBodyList'] != null ? GetPrNotificationBodyList.fromJson(json['GetPrNotificationBodyList']) : null;
getPRInformationList = json['PR_Information_List'] != null ? GetPRInformationList.fromJson(json['PR_Information_List']) : null;
if (json['GetQuotationAnalysisList'] != null) {
getQuotationAnalysisList = <GetQuotationAnalysisList>[];
json['GetQuotationAnalysisList'].forEach((v) {
@ -1602,6 +1606,10 @@ class GenericResponseModel {
data['GetPrNotificationBodyList'] = this.getPrNotificationBodyList!.toJson();
}
if (this.getPRInformationList != null) {
data['PR_Information_List'] = this.getPRInformationList!.toJson();
}
if (this.getQuotationAnalysisList != null) {
data['GetQuotationAnalysisList'] = this.getQuotationAnalysisList!.map((v) => v.toJson()).toList();
}

@ -158,6 +158,7 @@ class POLines {
String? nEEDBYDATE;
int? nOOFROWS;
int? pOHEADERID;
int? pOLINEID;
String? pROMISEDDATE;
String? pRNUM;
num? qUANTITY;
@ -181,6 +182,7 @@ class POLines {
this.nEEDBYDATE,
this.nOOFROWS,
this.pOHEADERID,
this.pOLINEID,
this.pROMISEDDATE,
this.pRNUM,
this.qUANTITY,
@ -204,6 +206,7 @@ class POLines {
nEEDBYDATE = json['NEED_BY_DATE'];
nOOFROWS = json['NO_OF_ROWS'];
pOHEADERID = json['PO_HEADER_ID'];
pOLINEID = json['PO_LINE_ID'];
pROMISEDDATE = json['PROMISED_DATE'];
pRNUM = json['PR_NUM'];
qUANTITY = json['QUANTITY'];
@ -229,6 +232,7 @@ class POLines {
data['NEED_BY_DATE'] = this.nEEDBYDATE;
data['NO_OF_ROWS'] = this.nOOFROWS;
data['PO_HEADER_ID'] = this.pOHEADERID;
data['PO_LINE_ID'] = this.pOLINEID;
data['PROMISED_DATE'] = this.pROMISEDDATE;
data['PR_NUM'] = this.pRNUM;
data['QUANTITY'] = this.qUANTITY;

@ -0,0 +1,125 @@
class GetPRInformationList {
List<PRHeader>? pRHeader;
List<PRLines>? pRLines;
String? pCURRENCYCODE;
GetPRInformationList({this.pRHeader, this.pRLines, this.pCURRENCYCODE});
GetPRInformationList.fromJson(Map<String, dynamic> json) {
if (json['PRHeader'] != null) {
pRHeader = <PRHeader>[];
json['PRHeader'].forEach((v) {
pRHeader!.add(new PRHeader.fromJson(v));
});
}
if (json['PRLines'] != null) {
pRLines = <PRLines>[];
json['PRLines'].forEach((v) {
pRLines!.add(new PRLines.fromJson(v));
});
}
pCURRENCYCODE = json['P_CURRENCY_CODE'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
if (this.pRHeader != null) {
data['PRHeader'] = this.pRHeader!.map((v) => v.toJson()).toList();
}
if (this.pRLines != null) {
data['PRLines'] = this.pRLines!.map((v) => v.toJson()).toList();
}
data['P_CURRENCY_CODE'] = this.pCURRENCYCODE;
return data;
}
}
class PRHeader {
String? dESCRIPTION;
String? pRNUMBER;
String? rEQUISITIONTOTAL;
String? tAXTOTAL;
PRHeader({this.dESCRIPTION, this.pRNUMBER, this.rEQUISITIONTOTAL, this.tAXTOTAL});
PRHeader.fromJson(Map<String, dynamic> json) {
dESCRIPTION = json['DESCRIPTION'];
pRNUMBER = json['PR_NUMBER'];
rEQUISITIONTOTAL = json['REQUISITION_TOTAL'];
tAXTOTAL = json['TAX_TOTAL'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['DESCRIPTION'] = this.dESCRIPTION;
data['PR_NUMBER'] = this.pRNUMBER;
data['REQUISITION_TOTAL'] = this.rEQUISITIONTOTAL;
data['TAX_TOTAL'] = this.tAXTOTAL;
return data;
}
}
class PRLines {
String? cOSTCENTER;
String? dESCRIPTION;
int? fROMROWNUM;
int? iTEMAMU;
String? iTEMCODE;
int? lINEAMOUNT;
int? lINENUM;
int? nOOFROWS;
int? qUANTITY;
int? rOWNUM;
int? tOROWNUM;
int? uNITPRICE;
String? uOM;
PRLines(
{this.cOSTCENTER,
this.dESCRIPTION,
this.fROMROWNUM,
this.iTEMAMU,
this.iTEMCODE,
this.lINEAMOUNT,
this.lINENUM,
this.nOOFROWS,
this.qUANTITY,
this.rOWNUM,
this.tOROWNUM,
this.uNITPRICE,
this.uOM});
PRLines.fromJson(Map<String, dynamic> json) {
cOSTCENTER = json['COST_CENTER'];
dESCRIPTION = json['DESCRIPTION'];
fROMROWNUM = json['FROM_ROW_NUM'];
iTEMAMU = json['ITEM_AMU'];
iTEMCODE = json['ITEM_CODE'];
lINEAMOUNT = json['LINE_AMOUNT'];
lINENUM = json['LINE_NUM'];
nOOFROWS = json['NO_OF_ROWS'];
qUANTITY = json['QUANTITY'];
rOWNUM = json['ROW_NUM'];
tOROWNUM = json['TO_ROW_NUM'];
uNITPRICE = json['UNIT_PRICE'];
uOM = json['UOM'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['COST_CENTER'] = this.cOSTCENTER;
data['DESCRIPTION'] = this.dESCRIPTION;
data['FROM_ROW_NUM'] = this.fROMROWNUM;
data['ITEM_AMU'] = this.iTEMAMU;
data['ITEM_CODE'] = this.iTEMCODE;
data['LINE_AMOUNT'] = this.lINEAMOUNT;
data['LINE_NUM'] = this.lINENUM;
data['NO_OF_ROWS'] = this.nOOFROWS;
data['QUANTITY'] = this.qUANTITY;
data['ROW_NUM'] = this.rOWNUM;
data['TO_ROW_NUM'] = this.tOROWNUM;
data['UNIT_PRICE'] = this.uNITPRICE;
data['UOM'] = this.uOM;
return data;
}
}

@ -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<RTCPeerConnection> _createPeerConnection() async {
// {"url": "stun:stun.l.google.com:19302"},
Map<String, dynamic> configuration = {
"iceServers": [
{"urls": 'stun:15.185.116.59:3478'},
{"urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin"}
]
};
Map<String, dynamic> 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<String, dynamic> 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<Object?>? params) {}
void onIceCandidateAsync(List<Object?>? params) {}
void onOfferAsync(List<Object?>? params) {}
void onAnswerOffer(List<Object?>? params) {}
void onHangUpAsync(List<Object?>? params) {}
void onCallDeclinedAsync(List<Object?>? params) {}
//// Invoke Methods
Future<void> invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async {
List<Object> 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');
}
}

File diff suppressed because it is too large Load Diff

@ -66,7 +66,11 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
if (attendanceTracking?.pSwipeIn != null) {
isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00");
int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00");
progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds);
if(isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) {
progress = 0;
} else {
progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds);
}
endTime = DateTime.now().millisecondsSinceEpoch + Duration(seconds: isTimeRemainingInSeconds).inMilliseconds;
}
notifyListeners();
@ -187,10 +191,10 @@ 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);
ticketBalance = (accrualList![1].accrualNetEntitlement ?? 0.0) + (accrualList![2].accrualNetEntitlement ?? 0.0) + (accrualList![3].accrualNetEntitlement ?? 0.0);
notifyListeners();
} catch (ex) {
isLeaveTicketBalanceLoading = false;
@ -241,7 +245,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);

@ -0,0 +1,46 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:wifi_iot/wifi_iot.dart';
class HmgConnectionProvider extends ChangeNotifier {
bool isConnectedToHMG = false;
Future<bool> checkHmgNetworkConnectivity() async {
if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
isConnectedToHMG = true;
} else {
isConnectedToHMG = false;
}
AppState().isConnectedToHMG = isConnectedToHMG;
return isConnectedToHMG;
}
void connectWithHmgNetwork() async {
try {
bool isConnected = await WiFiForIoTPlugin.connect("MOHEMM-CONNECT", password: "0987654321", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
if (isConnected) {
await WiFiForIoTPlugin.forceWifiUsage(true);
await Future.delayed(const Duration(seconds: 2));
isConnectedToHMG=true;
}
} catch (e) {
isConnectedToHMG = false;
AppState().isConnectedToHMG = isConnectedToHMG;
print("----------------o----");
print(e);
}
}
Future<bool> closeWifiRequest() async {
if (Platform.isAndroid) {
await WiFiForIoTPlugin.forceWifiUsage(false);
}
isConnectedToHMG = false;
AppState().isConnectedToHMG = isConnectedToHMG;
return await WiFiForIoTPlugin.disconnect();
}
}

@ -432,7 +432,7 @@ class _MonthlyAttendanceScreenState extends State<MonthlyAttendanceScreen> {
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(

@ -140,7 +140,7 @@ class _VacationRuleScreenState extends State<VacationRuleScreen> {
}
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);
}
}

@ -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<OutGoingCall> with SingleTickerProviderStateMixin {
AnimationController? _animationController;
CameraController? _controller;
late CameraController controller;
late List<CameraDescription> _cameras;
Future<void>? _initializeControllerFuture;
bool isCameraReady = false;
bool isMicOff = false;
bool isLoudSpeaker = false;
bool isCamOff = false;
late ChatCallProvider callProviderd;
@override
void initState() {
callProviderd = Provider.of<ChatCallProvider>(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<OutGoingCall> with SingleTickerProviderSt
return Stack(
alignment: FractionalOffset.center,
children: <Widget>[
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<OutGoingCall> with SingleTickerProviderSt
child: Container(
decoration: BoxDecoration(
color: MyColors.grey57Color.withOpacity(
0.7,
0.3,
),
),
child: Column(
@ -105,9 +106,9 @@ class _OutGoingCallState extends State<OutGoingCall> 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<OutGoingCall> with SingleTickerProviderSt
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
if (widget.isVideoCall!)
if (widget.isVideoCall)
RawMaterialButton(
onPressed: () {
_camOff();
@ -267,13 +268,10 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
}
void _runAnimation() async {
List<CameraDescription> 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<OutGoingCall> 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);

@ -8,6 +8,7 @@ import 'package:just_audio/just_audio.dart';
import 'package:mohem_flutter_app/api/chat/chat_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/my_custom_stream.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
@ -429,7 +430,7 @@ class ChatBubble extends StatelessWidget {
Widget getPlayer({required AudioPlayer player, required SingleUserChatModel modelData}) {
return StreamBuilder<PlayerState>(
stream: player!.playerStateStream,
stream: player.playerStateStream,
builder: (BuildContext context, AsyncSnapshot<PlayerState> snapshot) {
PlayerState? playerState = snapshot.data;
ProcessingState? processingState = playerState?.processingState;
@ -442,7 +443,7 @@ class ChatBubble extends StatelessWidget {
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return Icon(
return const Icon(
Icons.play_arrow,
size: 30,
color: MyColors.lightGreenColor,
@ -470,22 +471,3 @@ class ChatBubble extends StatelessWidget {
);
}
}
class MyCustomStream extends StreamAudioSource {
final Uint8List bytes;
MyCustomStream(this.bytes);
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= bytes.length;
return StreamAudioResponse(
sourceLength: bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(bytes.sublist(start, end)),
contentType: 'audio/aac',
);
}
}

@ -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<ChatDetailScreen> {
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<ChatDetailScreen> {
Widget build(BuildContext context) {
params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams;
data = Provider.of<ChatProviderModel>(context, listen: false);
// callPro = Provider.of<ChatCallProvider>(context, listen: false);
if (params != null) {
data.getSingleUserChatHistory(
senderUID: AppState().chatDetails!.response!.id!.toInt(),
@ -92,11 +99,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
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<ChatDetailScreen> {
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: <Widget>[
@ -342,45 +351,30 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
}
}
void makeCall({required String callType, required HubConnection con}) async {
void makeCall({required String callType}) async {
callPro.initCallListeners();
print("================== Make call Triggered ============================");
Map<String, dynamic> 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();
});
}
}

@ -54,11 +54,11 @@ class _ChatHomeState extends State<ChatHome> {
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);
// }
});
}
}

@ -0,0 +1,697 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/chat/chat_api_client.dart';
import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/create_group_request.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'
as groups;
import 'package:mohem_flutter_app/models/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
import 'package:provider/provider.dart';
class CreateGroupBottomSheet extends StatefulWidget {
int? notificationID;
String title, apiMode;
List<GetActionHistoryList>? actionHistoryList;
Function(ReplacementList) onSelectEmployee;
bool fromChat;
groups.GroupResponse groupDetails;
CreateGroupBottomSheet({
Key? key,
required this.title,
required this.apiMode,
this.notificationID,
this.actionHistoryList,
required this.onSelectEmployee,
required this.fromChat,
required this.groupDetails,
}) : super(key: key);
@override
State<CreateGroupBottomSheet> createState() => _CreateGroupBottomSheetState();
}
class _CreateGroupBottomSheetState extends State<CreateGroupBottomSheet> {
TextEditingController username = TextEditingController();
ScrollController sc = ScrollController();
bool isAudioCall = true;
bool isVideoCall = true;
bool isAttachments = true;
bool isShareScreen = true;
String searchText = "";
String groupName = "";
List<String>? optionsList = [
LocaleKeys.fullName.tr(),
LocaleKeys.username.tr(),
LocaleKeys.endDate.tr(),
];
List<GetFavoriteReplacements>? favUsersList;
List<ReplacementList>? replacementList;
List<ReplacementList>? favouriteUserList;
List<ReplacementList>? nonFavouriteUserList;
// Chat Items
late ChatProviderModel provider;
int _selectedSearchIndex = 0;
List<ChatUser> selectedUsers = [];
void fetchUserByInput({bool isNeedLoading = true}) async {
try {
Utils.showLoading(context);
replacementList = await WorkListApiClient().searchUserByInput(
userName: _selectedSearchIndex == 0 ? searchText : "",
userId: _selectedSearchIndex == 1 ? searchText : "",
email: _selectedSearchIndex == 2 ? searchText : "",
);
favouriteUserList = replacementList
?.where((ReplacementList element) => element.isFavorite ?? false)
.toList();
nonFavouriteUserList = replacementList
?.where((ReplacementList element) => !(element.isFavorite ?? false))
.toList();
Utils.hideLoading(context);
setState(() {});
} catch (e) {
Utils.hideLoading(context);
Utils.handleException(e, context, null);
}
if (isNeedLoading) Utils.hideLoading(context);
setState(() {});
return null;
}
void fetchChatUser({bool isNeedLoading = true}) async {
if (provider.pageNo == 1) provider.chatUsersList!.clear();
try {
Utils.showLoading(context);
await ChatApiClient()
.getChatMemberFromSearch(searchText,
AppState().chatDetails!.response!.id!, provider.pageNo)
.then((ChatUserModel value) {
if (value.response != null) {
if (provider.pageNo == 1) {
provider.chatUsersList = value.response;
} else {
print("--------------------------Added More----------------------");
provider.chatUsersList!.addAll(value.response!);
}
}
});
provider.chatUsersList!.removeWhere((ChatUser element) =>
element.id == AppState().chatDetails!.response!.id);
Utils.hideLoading(context);
setState(() {});
} catch (e) {
Utils.hideLoading(context);
Utils.handleException(e, context, null);
}
if (isNeedLoading) Utils.hideLoading(context);
setState(() {});
return null;
}
void scrollListener() async {
if (sc.position.pixels == sc.position.maxScrollExtent) {
provider.pageNo++;
logger.w(provider.chatUsersList!.length);
logger.w(provider.pageNo);
fetchChatUser();
}
}
@override
void initState() {
super.initState();
sc.addListener(scrollListener);
provider = Provider.of<ChatProviderModel>(context, listen: false);
if (widget.groupDetails.groupName !=null) {
setState(() {
groupName = widget.groupDetails.groupName!;
isAudioCall = widget.groupDetails.canAudioC!;
isVideoCall = widget.groupDetails.canVideoC!;
isAttachments = widget.groupDetails.canAttach!;
isShareScreen = widget.groupDetails.canShareS!;
for (groups.GroupUserList items in widget.groupDetails.groupUserList!) {
{
selectedUsers.add(ChatUser.fromJson(items.toJson()));
}
}
});
}
}
@override
void dispose() {
super.dispose();
provider.chatUsersList = [];
provider.pageNo = 1;
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height - 100,
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.title.toText24(isBold: true),
21.height,
Row(
children: [
DynamicTextFieldWidget(
"Group Name",
groupName.isEmpty ? "Please enter group name" : groupName,
inputAction: TextInputAction.done,
onChange: (String text) {
groupName = text;
setState(() {});
},
).expanded,
],
),
//11.height,
Row(
children: [
SizedBox(
height: 35,
child: CheckboxListTile(
contentPadding: EdgeInsets.zero,
title: "Audio Call".toText10(),
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
side: BorderSide(
width: 1.5,
color: Theme.of(context).unselectedWidgetColor),
value: isAudioCall,
onChanged: (bool? newValue) {
setState(() {
isAudioCall = newValue!;
});
},
controlAffinity: ListTileControlAffinity
.leading, // <-- leading Checkbox
)).expanded,
SizedBox(
height: 35,
child: CheckboxListTile(
contentPadding: EdgeInsets.zero,
title: "Video Call".toText10(),
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
value: isVideoCall,
onChanged: (bool? newValue) {
setState(() {
isVideoCall = newValue!;
});
},
controlAffinity: ListTileControlAffinity
.leading, // <-- leading Checkbox
)).expanded
],
),
Row(
children: [
SizedBox(
height: 35,
child: CheckboxListTile(
contentPadding: EdgeInsets.zero,
title: "Attachments".toText10(),
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
value: isAttachments,
onChanged: (bool? newValue) {
setState(() {
isAttachments = newValue!;
});
},
controlAffinity: ListTileControlAffinity
.leading, // <-- leading Checkbox
)).expanded,
SizedBox(
height: 35,
child: CheckboxListTile(
contentPadding: EdgeInsets.zero,
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
title: "Share Screen".toText10(),
value: isShareScreen,
onChanged: (bool? newValue) {
setState(() {
isShareScreen = newValue!;
});
},
controlAffinity: ListTileControlAffinity
.leading, // <-- leading Checkbox
)).expanded
],
),
11.height,
"User Search".toText16(),
11.height,
Row(
children: [
radioOption(widget.fromChat ? "UserId" : "Name", 0,
_selectedSearchIndex),
radioOption("User Name", 1, _selectedSearchIndex),
radioOption("Email", 2, _selectedSearchIndex),
],
),
14.height,
Row(
children: [
DynamicTextFieldWidget(
"Search",
"Search By Username",
inputAction: TextInputAction.done,
suffixIconData: Icons.search,
onChange: (String text) {
searchText = text;
setState(() {});
},
).expanded,
IconButton(
constraints: const BoxConstraints(),
onPressed: () async {
await SystemChannels.textInput
.invokeMethod('TextInput.hide');
widget.fromChat ? fetchChatUser() : fetchUserByInput();
},
icon: const Icon(Icons.search),
)
],
),
if (replacementList != null)
replacementList!.isEmpty
? Utils.getNoDataWidget(context).expanded
: ListView(
physics: const BouncingScrollPhysics(),
padding: EdgeInsets.only(top: 21, bottom: 8),
children: [
if (favouriteUserList?.isNotEmpty ?? false) ...[
"Favorites".toText16(),
12.height,
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int index) =>
employeeItemView(favouriteUserList![index]),
separatorBuilder:
(BuildContext cxt, int index) => Container(
height: 1,
color: MyColors.borderE3Color,
),
itemCount: favouriteUserList?.length ?? 0),
12.height,
],
if (nonFavouriteUserList?.isNotEmpty ?? false) ...[
"Related".toText16(),
12.height,
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int index) =>
employeeItemView(
nonFavouriteUserList![index]),
separatorBuilder:
(BuildContext cxt, int index) => Container(
height: 1,
color: MyColors.borderE3Color,
),
itemCount: nonFavouriteUserList?.length ?? 0),
],
],
).expanded,
selectedUsers!.isNotEmpty
? SizedBox(
height: 95,
child: ListView.builder(
physics: const ClampingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: selectedUsers!.length,
itemBuilder: (BuildContext context, int index2) {
return Stack(children: [
Column(
children: [
12.height,
Stack(children: [
Container(
padding:const EdgeInsets.all(5),
child: SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
)),
Positioned(
right: 0,
top: 0,
child: InkWell(
child: SvgPicture.asset(
'assets/icons/close.svg',
height:15,
width:15
),
onTap: () {
setState(() {
// provider.chatUsersList![index]
// .isChecked = false;
List<ChatUser> user = provider
.chatUsersList!
.where((ChatUser value) =>
value.userName ==
selectedUsers[index2]
.userName)
.toList();
if (user.isNotEmpty) {
user.first.isChecked = false;
}
selectedUsers.remove(
selectedUsers[index2]);
});
},
))
],),
(selectedUsers![index2]
.userName!
.replaceFirst(".", " ")
.capitalizeFirstofEach ??
"")
.toText12(color: MyColors.darkTextColor)
.paddingOnly(left: 5, top: 5),
selectedUsers![index2].isTyping!
? 'Typing...'
.toText10(
color: MyColors.textMixColor,
)
.paddingOnly(left: 5.0)
: const SizedBox()
],
),
// IconButton(onPressed: (){}, icon: const Icon(Icons.close_outlined, color: Colors.red, size: 20)),
]);
}))
: 0.height,
if (widget.fromChat)
if (provider.chatUsersList != null && widget.fromChat)
provider.chatUsersList!.isEmpty
? Column(
children: [
20.height,
Utils.getNoDataWidget(context),
],
)
: ListView.separated(
itemCount: provider.chatUsersList!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
controller: sc,
padding: const EdgeInsets.only(bottom: 80.0, top: 20),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: Row(
children: [
Stack(
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: provider
.chatUsersList![index]
.userStatus ==
1
? MyColors.green2DColor
: Colors.red,
),
).circle(10),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
(provider.chatUsersList![index].userName!
.replaceFirst(".", " ")
.capitalizeFirstofEach ??
"")
.toText14(
color: MyColors.darkTextColor)
.paddingOnly(left: 11, top: 13),
provider.chatUsersList![index].isTyping!
? 'Typing...'
.toText10(
color: MyColors.textMixColor,
)
.paddingOnly(left: 11.0)
: const SizedBox()
],
).expanded,
SizedBox(
width: 60,
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
if (provider.chatUsersList![index]
.unreadMessageCount! >
0)
Container(
alignment: Alignment.center,
width: 18,
height: 18,
decoration: const BoxDecoration(
color: MyColors.redColor,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: (provider
.chatUsersList![index]
.unreadMessageCount!
.toString())
.toText10(
color: MyColors.white,
)
.center,
).paddingOnly(right: 10).center,
Checkbox(
value: provider
.chatUsersList![index].isChecked,
shape: CircleBorder(),
onChanged: (bool? value) {
setState(() {
provider.chatUsersList![index]
.isChecked = value;
if (provider.chatUsersList![index]
.isChecked ==
true) {
selectedUsers.add(provider
.chatUsersList![index]);
} else {
selectedUsers.remove(provider
.chatUsersList![index]);
}
});
},
)
],
),
),
],
),
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(color: MyColors.lightGreyE5Color)
.paddingOnly(left: 59),
).expanded,
],
).paddingOnly(left: 21, right: 21, bottom: 0, top: 21).expanded,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
DefaultButton(
LocaleKeys.cancel.tr(),
() {
Navigator.pop(context);
provider.chatUsersList = [];
provider.pageNo = 1;
},
textColor: MyColors.grey3AColor,
colors: const [
Color(0xffE6E6E6),
Color(0xffE6E6E6),
],
).paddingOnly(left: 14, right: 14, bottom: 15, top: 10).expanded,
DefaultButton(
LocaleKeys.submit.tr(),
() {
// Navigator.pop(context);
// provider.chatUsersList = [];
// provider.pageNo = 1;
createGroup();
},
textColor: MyColors.whiteColor,
colors: const [
Color(0xff32D892),
Color(0xff1AB170),
],
).paddingOnly(left: 15, right: 15, bottom: 15, top: 10).expanded,
],
)
],
),
);
}
Widget employeeItemView(ReplacementList replacement) {
return InkWell(
onTap: () {
Navigator.pop(context);
widget.onSelectEmployee(replacement);
},
child: SizedBox(
height: 50,
child: Row(
children: [
CircularAvatar(
url: replacement.employeeImage ?? "",
height: 30,
width: 30,
isImageBase64: true,
),
16.width,
Expanded(
child: (replacement.employeeDisplayName ?? "").toText12(),
),
Icon(Icons.star,
size: 16,
color: replacement.isFavorite!
? MyColors.yellowFavColor
: MyColors.borderCEColor),
],
),
),
);
}
Widget radioOption(String title, int value, int groupValue) {
return Row(
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(color: MyColors.borderColor, width: 1),
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
padding: const EdgeInsets.all(4),
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: value == groupValue
? MyColors.grey3AColor
: Colors.transparent,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
),
),
9.width,
title.toText12(color: MyColors.grey57Color)
],
).onPress(() {
_selectedSearchIndex = value;
setState(() {});
}).expanded;
}
void createGroup() async {
RegExp validCharacters = RegExp(r'^[a-zA-Z0-9_\-=@,\.;]+$');
if (!validCharacters.hasMatch(groupName)) {
Utils.showToast("Please enter valid group Name");
} else if (groupName.length < 10) {
Utils.showToast("Group name should be minimum 10 character long");
} else {
List<ChatUser>? mainUsers = [];
ChatUser admin =
ChatUser.fromJson(AppState().chatDetails!.response!.toJson());
admin.isAdmin = true;
admin.userStatus = 2;
admin.unreadMessageCount = 0;
admin.totalCount = 0;
mainUsers.add(admin);
CreateGroupRequest request = CreateGroupRequest(
groupUserList: [...selectedUsers, ...mainUsers].toList(),
canArchive: false,
isMeeting: false,
canShareS: isShareScreen,
canAudioC: isAudioCall,
canAttach: isAttachments,
canVideoC: isVideoCall,
groupName: groupName,
adminUserId: AppState().chatDetails!.response!.id);
if(widget.groupDetails!.groupId !=null){
request.groupId =widget.groupDetails!.groupId;
await provider.updateGroupAndUsers(request);
}else {
await provider.addGroupAndUsers(request);
}
Navigator.pop(context);
}
}
}

@ -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<CustomAutoDirection> {
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);
}
}

@ -5,12 +5,19 @@ import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart';
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/ui/chat/create_group.dart';
import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart';
import 'package:mohem_flutter_app/ui/chat/manage_group.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
@ -29,7 +36,6 @@ class _GropChatHomeScreenState extends State<GropChatHomeScreen> {
@override
void initState() {
super.initState();
}
@ -47,89 +53,146 @@ class _GropChatHomeScreenState extends State<GropChatHomeScreen> {
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return m.isLoading
? ChatHomeShimmer(
isDetailedScreen: false,
)
isDetailedScreen: false,
)
: Column(
children: <Widget>[
TextField(
controller: m.searchGroup,
style: const TextStyle(color: MyColors.darkTextColor, fontWeight: FontWeight.w500, fontSize: 12),
onChanged: (String val) {
m.filter(val);
},
decoration: InputDecoration(
border: fieldBorder(radius: 5, color: 0xFFE5E5E5),
focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5),
enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5),
contentPadding: const EdgeInsets.all(11),
hintText: LocaleKeys.searchGroup.tr(),
hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500, fontSize: 12),
filled: true,
fillColor: MyColors.greyF7Color,
suffixIconConstraints: const BoxConstraints(),
suffixIcon: m.search.text.isNotEmpty
? IconButton(
constraints: const BoxConstraints(),
onPressed: () {
m.clearSelections();
},
icon: const Icon(Icons.clear, size: 22),
color: MyColors.redA3Color,
)
: null,
),
).paddingOnly(top: 20, bottom: 14),
if (m.userGroups.response != null)
ListView.separated(
itemCount: m.userGroups.response!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.only(bottom: 80.0),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: Row(
children: [
Container(
alignment: Alignment.center,
width: 48,
height: 48,
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0),
border: Border.all(width: 1, color: Colors.black),
),
child: SvgPicture.asset(
"assets/images/chat-group.svg",
)),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(m.userGroups?.response![index].groupName!.toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 16)
)!.expanded,
])
],
children: <Widget>[
TextField(
controller: m.searchGroup,
style: const TextStyle(
color: MyColors.darkTextColor,
fontWeight: FontWeight.w500,
fontSize: 12),
onChanged: (String val) {
m.filterGroups(val);
},
decoration: InputDecoration(
border: fieldBorder(radius: 5, color: 0xFFE5E5E5),
focusedBorder:
fieldBorder(radius: 5, color: 0xFFE5E5E5),
enabledBorder:
fieldBorder(radius: 5, color: 0xFFE5E5E5),
contentPadding: const EdgeInsets.all(11),
hintText: LocaleKeys.searchGroup.tr(),
hintStyle: const TextStyle(
color: MyColors.lightTextColor,
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w500,
fontSize: 12),
filled: true,
fillColor: MyColors.greyF7Color,
suffixIconConstraints: const BoxConstraints(),
suffixIcon: m.search.text.isNotEmpty
? IconButton(
constraints: const BoxConstraints(),
onPressed: () {
m.clearSelections();
},
icon: const Icon(Icons.clear, size: 22),
color: MyColors.redA3Color,
)
: null,
),
).onPress(() {
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: ChatDetailedScreenParams(m.searchedChats![index], false),
).then((Object? value) {
m.clearSelections();
m.notifyListeners();
});
});
},
separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.black).paddingOnly(left: 59),
).expanded,
],
).paddingOnly(left: 21, right: 21);
).paddingOnly(top: 20, bottom: 14),
if (m.uGroups != null)
ListView.separated(
itemCount: m.uGroups!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.only(bottom: 80.0),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: Row(
children: [
Container(
alignment: Alignment.center,
width: 48,
height: 48,
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0),
border: Border.all(
width: 1, color: Colors.black),
),
child: SvgPicture.asset(
"assets/images/chat-group.svg",
)),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
(m.uGroups![index]
.groupName!
.toText14(
color: MyColors.darkTextColor)
.paddingOnly(left: 11, top: 16))!,
]),
Align(
alignment: Alignment.centerRight,
child: PopupMenuButton(
onSelected: (String value){
goToSelected(m.uGroups![index], m, value);
},
itemBuilder: (context) => [
PopupMenuItem<String>(
value: '1',
enabled: m.uGroups![index].isAdmin ?? false,
child: (LocaleKeys.edit
.tr()
.toText14(color: m.userGroups?.groupresponse![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor)
.paddingOnly(left: 11, top: 16))),
PopupMenuItem<String>(
value: '2',
enabled: m.uGroups![index].isAdmin ?? false,
child: (LocaleKeys.delete
.tr()
.toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor)
.paddingOnly(left: 11, top: 16))),
PopupMenuItem<String>(
value: '3',
enabled: m.uGroups![index].isAdmin ?? false,
onTap: () {
},
child: (LocaleKeys.manage
.tr()
.toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor)
.paddingOnly(left: 11, top: 16))),
PopupMenuItem<String>(
value: '4',
child: (LocaleKeys.members
.tr()
.toText14(color: MyColors.darkTextColor)
.paddingOnly(left: 11, top: 16))),
],
)
)
.expanded
],
),
).onPress(() {
chatDetails(m.uGroups![index], m,);
// Navigator.pushNamed(
// context,
// AppRoutes.chatDetailed,
// arguments: ChatDetailedScreenParams(
// m.searchedChats![index], false),
// ).then((Object? value) {
// m.clearSelections();
// m.notifyListeners();
// });
});
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(color: MyColors.black)
.paddingOnly(left: 59),
).expanded,
],
).paddingOnly(left: 21, right: 21);
},
),
floatingActionButton: FloatingActionButton(
@ -155,15 +218,16 @@ class _GropChatHomeScreenState extends State<GropChatHomeScreen> {
),
),
onPressed: () async {
print(AppState().chatDetails!.response!.token);
showMyBottomSheet(
context,
callBackFunc: () {},
child: SearchEmployeeBottomSheet(
title: LocaleKeys.searchForEmployee.tr(),
child: CreateGroupBottomSheet(
title:"Add users to the group",
apiMode: LocaleKeys.delegate.tr(),
fromChat: true,
onSelectEmployee: (_selectedEmployee) {},
onSelectEmployee: (ReplacementList _selectedEmployee) {},
groupDetails:GroupResponse(),
),
);
},
@ -179,4 +243,65 @@ class _GropChatHomeScreenState extends State<GropChatHomeScreen> {
),
);
}
void goToSelected(GroupResponse? groupDetails, ChatProviderModel m, String value) {
switch(value) {
case '1':
editGroup(groupDetails, m);
break;
case '2':
deleteGroup(groupDetails, m, context);
break;
case '3':
Navigator.pushNamed(context,
AppRoutes.manageGroup,
arguments: groupDetails ,
);
break;
case '4':
Navigator.pushNamed(context,
AppRoutes.groupMembers,
arguments: groupDetails!.groupUserList,
);
break;
}
}
void deleteGroup(
GroupResponse? groupDetails, ChatProviderModel m, BuildContext context) {
groupDetails!.groupUserList;
Utils.confirmDialog(
context,
LocaleKeys.areYouSureWantTodelete.tr(),
onTap: () {
Navigator.pop(context);
m.deleteGroup(groupDetails);
},
);
}
Future<void> chatDetails(GroupResponse? groupDetails, ChatProviderModel m) async {
// await m.getGroupChatHistory(groupDetails!);
Navigator.pushNamed(context,
AppRoutes.groupChatDetailed,
arguments:
GroupChatDetailedScreenParams(
groupDetails,
false));
}
Future<void> editGroup(GroupResponse? groupDetails, ChatProviderModel m) async {
showMyBottomSheet(
context,
callBackFunc: () {},
child: CreateGroupBottomSheet(
title:"Edit Group",
apiMode: LocaleKeys.delegate.tr(),
fromChat: true,
onSelectEmployee: (ReplacementList _selectedEmployee) {},
groupDetails: groupDetails!,
),
);
}
}

@ -0,0 +1,643 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:just_audio/just_audio.dart';
import 'package:mohem_flutter_app/api/chat/chat_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/my_custom_stream.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/chat_full_image_preview.dart';
import 'package:mohem_flutter_app/ui/chat/common.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
class GroupChatBubble extends StatelessWidget {
GroupChatBubble({Key? key, required this.dateTime, required this.cItem})
: super(key: key);
final String dateTime;
final GetGroupChatHistoryAsync cItem;
bool isCurrentUser = false;
bool isSeen = false;
bool isReplied = false;
bool isVoice = false;
int? fileTypeID;
String? fileTypeName;
late ChatProviderModel provider;
String? fileTypeDescription;
bool isDelivered = false;
String userName = '';
late Offset screenOffset;
void makeAssign() {
isCurrentUser = cItem.currentUserId == AppState().chatDetails!.response!.id
? true
: false;
isSeen = cItem.isSeen == true ? true : false;
isReplied = cItem.groupChatReplyResponse != null ? true : false;
// isVoice = cItem.fileTypeId == 13 && cItem.voiceController != null ? true : false;
fileTypeID = cItem.fileTypeId;
fileTypeName = cItem.fileTypeResponse != null
? cItem.fileTypeResponse!.fileTypeName
: "";
fileTypeDescription = cItem.fileTypeResponse != null
? cItem.fileTypeResponse!.fileTypeDescription
: "";
isDelivered = cItem.currentUserId == AppState().chatDetails!.response!.id &&
cItem.isDelivered == true
? true
: false;
userName = AppState().chatDetails!.response!.userName ==
cItem.currentUserName.toString()
? "You"
: cItem.currentUserName.toString();
}
void playVoice(
BuildContext context, {
required SingleUserChatModel data,
}) async {
if (data.voice != null && data.voice!.existsSync()) {
if (Platform.isIOS) {
Duration? duration = await data.voiceController!
.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync()));
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.setVolume(1.0);
await data.voiceController!.load();
data.voiceController!.play();
} else {
await data.voiceController!.setFilePath(data!.voice!.path);
Duration? duration = await data.voiceController!.load();
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.play();
}
} else {
Utils.showLoading(context);
Uint8List encodedString = await ChatApiClient().downloadURL(
fileName: data.contant!,
fileTypeDescription: provider.getFileTypeDescription(
data.fileTypeResponse!.fileTypeName ?? ""));
// try {
File sFile = await provider.downChatVoice(
encodedString, data.fileTypeResponse!.fileTypeName ?? "", data);
if (sFile.path.isEmpty) {
logger.d("Path Is Emptyyyyyyy");
} else {
logger.d("Path Exsists");
}
data.voice = sFile;
if (Platform.isIOS) {
logger.d("isIOS");
Duration? duration = await data.voiceController!
.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync()));
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.setVolume(1.0);
await data.voiceController!.load();
Utils.hideLoading(context);
data.voiceController!.play();
} else {
Duration? duration =
await data.voiceController!.setFilePath(sFile.path);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.seek(duration);
Utils.hideLoading(context);
await data.voiceController!.play();
}
}
}
void pausePlaying(BuildContext context,
{required SingleUserChatModel data}) async {
await data.voiceController!.pause();
}
void rePlay(BuildContext context, {required SingleUserChatModel data}) async {
if (data.voice != null && data.voice!.existsSync()) {
await data.voiceController!.seek(Duration.zero);
await data.voiceController!.play();
}
}
Stream<PositionData> get _positionDataStream =>
Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
cItem.voiceController!.positionStream,
cItem.voiceController!.bufferedPositionStream,
cItem.voiceController!.durationStream,
(Duration position, Duration bufferedPosition, Duration? duration) =>
PositionData(
position, bufferedPosition, duration ?? Duration.zero));
@override
Widget build(BuildContext context) {
Size windowSize = MediaQuery.of(context).size;
screenOffset = Offset(windowSize.width / 2, windowSize.height / 2);
makeAssign();
provider = Provider.of<ChatProviderModel>(context, listen: false);
return isCurrentUser ? currentUser(context) : receiptUser(context);
}
Widget currentUser(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (isReplied)
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 6,
color: isCurrentUser
? MyColors.gradiantStartColor
: MyColors.white),
),
color: isCurrentUser
? MyColors.black.withOpacity(0.10)
: MyColors.black.withOpacity(0.30),
),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(userName)
.toText12(
color: MyColors.gradiantStartColor, isBold: false)
.paddingOnly(right: 5, top: 5, bottom: 0, left: 5),
Directionality(
textDirection: provider.getTextDirection(
cItem.groupChatReplyResponse != null
? cItem.groupChatReplyResponse!.contant
.toString()
: ""),
child: (cItem.groupChatReplyResponse != null
? cItem.groupChatReplyResponse!.contant
.toString()
: "")
.toText10(
color: isCurrentUser
? MyColors.grey71Color
: MyColors.white.withOpacity(0.5),
isBold: false,
maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
),
],
).expanded,
if (cItem.groupChatReplyResponse != null)
if (cItem.groupChatReplyResponse!.fileTypeId == 12 ||
cItem.groupChatReplyResponse!.fileTypeId == 3 ||
cItem.groupChatReplyResponse!.fileTypeId == 4)
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: SizedBox(
height: 32,
width: 32,
child: showImage(
isReplyPreview: false,
fileName:
cItem.groupChatReplyResponse!.contant!,
fileTypeDescription: cItem
.groupChatReplyResponse!
.fileTypeResponse!
.fileTypeDescription ??
"image/jpg")),
).paddingOnly(left: 10, right: 10, bottom: 16, top: 16),
],
),
),
).paddingOnly(bottom: 7).onPress(() {
// provider.scrollToMsg(cItem);
}),
if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3)
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: SizedBox(
height: 140,
width: 227,
child: showImage(
isReplyPreview: false,
fileName: cItem.contant!,
fileTypeDescription:
cItem.fileTypeResponse!.fileTypeDescription)
.onPress(() {
showDialog(
context: context,
anchorPoint: screenOffset,
builder: (BuildContext context) => ChatImagePreviewScreen(
imgTitle: cItem.contant!, img: cItem.image!),
);
}),
),
).paddingOnly(bottom: 4),
if (fileTypeID == 13 && cItem.voiceController != null)
currentWaveBubble(context, cItem)
else
Row(
children: [
if (fileTypeID == 1 ||
fileTypeID == 5 ||
fileTypeID == 7 ||
fileTypeID == 6 ||
fileTypeID == 8
// || fileTypeID == 2
)
SvgPicture.asset(provider.getType(fileTypeName ?? ""),
height: 30,
width: 22,
alignment: Alignment.center,
fit: BoxFit.cover)
.paddingOnly(left: 0, right: 10),
Directionality(
textDirection: provider.getTextDirection(cItem.contant ?? ""),
child: (cItem.contant ?? "").toText12().expanded),
if (fileTypeID == 1 ||
fileTypeID == 5 ||
fileTypeID == 7 ||
fileTypeID == 6 ||
fileTypeID == 8
//|| fileTypeID == 2
)
const Icon(Icons.remove_red_eye, size: 16)
],
),
Align(
alignment: Alignment.centerRight,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
dateTime.toText10(
color: MyColors.grey41Color.withOpacity(.5),
),
7.width,
Icon(isDelivered ? Icons.done_all : Icons.done_all,
color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor,
size: 14),
],
),
),
],
)
.paddingOnly(top: 11, left: 13, right: 13, bottom: 5)
.objectContainerView(disablePadding: true)
.paddingOnly(left: MediaQuery.of(context).size.width * 0.3);
}
Widget receiptUser(BuildContext context) {
return Container(
padding: const EdgeInsets.only(top: 5, left: 8, right: 13, bottom: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
gradient: const LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: <Color>[
MyColors.gradiantEndColor,
MyColors.gradiantStartColor
],
),
),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
if (isReplied)
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 6,
color: isCurrentUser
? MyColors.gradiantStartColor
: MyColors.white)),
color: isCurrentUser
? MyColors.black.withOpacity(0.10)
: MyColors.black.withOpacity(0.30),
),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(userName)
.toText12(
color: MyColors.gradiantStartColor,
isBold: false)
.paddingOnly(right: 5, top: 5, bottom: 0, left: 5),
Directionality(
textDirection: provider.getTextDirection(
cItem.groupChatReplyResponse != null
? cItem.groupChatReplyResponse!.contant
.toString()
: ""),
child: (cItem.groupChatReplyResponse != null
? cItem.groupChatReplyResponse!.contant
.toString()
: "")
.toText10(
color: isCurrentUser
? MyColors.grey71Color
: MyColors.white.withOpacity(0.5),
isBold: false,
maxlines: 4)
.paddingOnly(
right: 5, top: 5, bottom: 8, left: 5),
),
],
).expanded,
if (cItem.groupChatReplyResponse != null)
if (cItem.groupChatReplyResponse!.fileTypeId == 12 ||
cItem.groupChatReplyResponse!.fileTypeId == 3 ||
cItem.groupChatReplyResponse!.fileTypeId == 4)
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: SizedBox(
height: 32,
width: 32,
child: showImage(
isReplyPreview: true,
fileName:
cItem.groupChatReplyResponse!.contant!,
fileTypeDescription: cItem
.groupChatReplyResponse!
.fileTypeResponse!
.fileTypeDescription ??
"image/jpg"),
),
).paddingOnly(left: 10, right: 10, bottom: 16, top: 16)
],
),
),
).paddingOnly(bottom: 7).onPress(() {
// provider.scrollToMsg(cItem);
}),
if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3)
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: SizedBox(
height: 140,
width: 227,
child: showImage(
isReplyPreview: false,
fileName: cItem.contant ?? "",
fileTypeDescription:
cItem.fileTypeResponse!.fileTypeDescription ??
"image/jpg")
.onPress(() {
showDialog(
context: context,
anchorPoint: screenOffset,
builder: (BuildContext context) => ChatImagePreviewScreen(
imgTitle: cItem.contant ?? "", img: cItem.image!),
);
}),
),
).paddingOnly(bottom: 4),
if (fileTypeID == 13 && cItem.voiceController != null)
recipetWaveBubble(context, cItem)
else
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cItem.currentUserName!.toText10(
color: Colors.black,
).paddingOnly(bottom: 5),
Row(
children: [
if (fileTypeID == 1 ||
fileTypeID == 5 ||
fileTypeID == 7 ||
fileTypeID == 6 ||
fileTypeID == 8
// || fileTypeID == 2
)
SvgPicture.asset(provider.getType(fileTypeName ?? ""),
height: 30,
width: 22,
alignment: Alignment.center,
fit: BoxFit.cover)
.paddingOnly(left: 0, right: 10),
Directionality(
textDirection:
provider.getTextDirection(cItem.contant ?? ""),
child: (cItem.contant ?? "")
.toText12(color: Colors.white)
.expanded),
if (fileTypeID == 1 ||
fileTypeID == 5 ||
fileTypeID == 7 ||
fileTypeID == 6 ||
fileTypeID == 8
//|| fileTypeID == 2
)
const Icon(Icons.remove_red_eye,
color: Colors.white, size: 16)
],
),
Align(
alignment: Alignment.topRight,
child: dateTime.toText10(
color: Colors.white.withOpacity(.71),
).paddingOnly(top:5),
),
],
),
])).paddingOnly(right: MediaQuery.of(context).size.width * 0.3);
}
Widget voiceMsg(BuildContext context) {
return Container();
}
Widget showImage(
{required bool isReplyPreview,
required String fileName,
required String fileTypeDescription}) {
if (cItem.isImageLoaded! && cItem.image != null) {
return Image.memory(
cItem.image!,
height: isReplyPreview ? 32 : 140,
width: isReplyPreview ? 32 : 227,
fit: BoxFit.cover,
alignment: Alignment.center,
);
} else {
return FutureBuilder<Uint8List>(
future: ChatApiClient().downloadURL(
fileName: fileName, fileTypeDescription: fileTypeDescription),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState != ConnectionState.waiting) {
if (snapshot.data == null) {
return const SizedBox();
} else {
cItem.image = snapshot.data;
cItem.isImageLoaded = true;
return Image.memory(
snapshot.data,
height: isReplyPreview ? 32 : 140,
width: isReplyPreview ? 32 : 227,
fit: BoxFit.cover,
alignment: Alignment.center,
);
}
} else {
return SizedBox(
height: isReplyPreview ? 32 : 140,
width: isReplyPreview ? 32 : 227,
).toShimmer();
}
},
);
}
}
Widget currentWaveBubble(
BuildContext context, GetGroupChatHistoryAsync data) {
return Container(
margin: const EdgeInsets.all(0),
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 6,
color:
isCurrentUser ? MyColors.gradiantStartColor : MyColors.white),
),
color: isCurrentUser
? MyColors.black.withOpacity(0.10)
: MyColors.black.withOpacity(0.30),
),
child: Row(
children: [
//need to check and verify for group hence for now commented
// getPlayer(player: data.voiceController!, modelData: data),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder:
(BuildContext context, AsyncSnapshot<PositionData> snapshot) {
PositionData? positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition:
positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: data.voiceController!.seek,
).expanded;
},
),
],
),
).circle(5);
}
Widget recipetWaveBubble(
BuildContext context, GetGroupChatHistoryAsync data) {
return Container(
margin: const EdgeInsets.all(0),
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 6,
color:
isCurrentUser ? MyColors.gradiantStartColor : MyColors.white),
),
color: isCurrentUser
? MyColors.black.withOpacity(0.10)
: MyColors.black.withOpacity(0.30),
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
//commented to verify after
//getPlayer(player: data.voiceController!, modelData: data),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder:
(BuildContext context, AsyncSnapshot<PositionData> snapshot) {
PositionData? positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition:
positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: data.voiceController!.seek,
).expanded;
},
),
],
),
).circle(5);
}
Widget getPlayer(
{required AudioPlayer player, required SingleUserChatModel modelData}) {
return StreamBuilder<PlayerState>(
stream: player.playerStateStream,
builder: (BuildContext context, AsyncSnapshot<PlayerState> snapshot) {
PlayerState? playerState = snapshot.data;
ProcessingState? processingState = playerState?.processingState;
bool? playing = playerState?.playing;
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 30.0,
height: 30.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return const Icon(
Icons.play_arrow,
size: 30,
color: MyColors.lightGreenColor,
).onPress(() {
playVoice(context, data: modelData);
});
} else if (processingState != ProcessingState.completed) {
return const Icon(
Icons.pause,
size: 30,
color: MyColors.lightGreenColor,
).onPress(() {
pausePlaying(context, data: modelData);
});
} else {
return const Icon(
Icons.replay,
size: 30,
color: MyColors.lightGreenColor,
).onPress(() {
rePlay(context, data: modelData);
});
}
},
);
}
}

@ -0,0 +1,384 @@
import 'dart:async';
import 'dart:convert';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart';
import 'package:mohem_flutter_app/provider/chat_call_provider.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/custom_auto_direction.dart';
import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart';
import 'package:mohem_flutter_app/ui/chat/common.dart';
import 'package:mohem_flutter_app/ui/chat/group_chat_bubble.dart';
import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:signalr_netcore/signalr_client.dart';
import 'package:swipe_to/swipe_to.dart';
class GroupChatDetailedScreenParams {
GroupResponse? groupChatDetails;
bool? isNewChat;
GroupChatDetailedScreenParams(this.groupChatDetails, this.isNewChat);
}
class GroupChatDetailScreen extends StatefulWidget {
const GroupChatDetailScreen({Key? key}) : super(key: key);
@override
State<GroupChatDetailScreen> createState() => _GroupChatDetailScreenState();
}
class _GroupChatDetailScreenState extends State<GroupChatDetailScreen> {
final RefreshController _rc = RefreshController(initialRefresh: false);
late ChatProviderModel data;
late ChatCallProvider callPro;
GroupChatDetailedScreenParams? params;
// var textDirection = TextDirection.RTL;
void getMoreChat() async {
if (params != null) {
data.paginationVal = data.paginationVal + 10;
if (params != null) {
data.getGroupChatHistory(params!.groupChatDetails!
// senderUID: AppState().chatDetails!.response!.id!.toInt(),
// receiverUID: params!.groupChatDetails!.groupId!,
// loadMore: true,
// isNewChat: false,
);
}
}
await Future.delayed(
const Duration(milliseconds: 1000),
);
_rc.loadComplete();
}
@override
void dispose() {
data.disposeAudio();
super.dispose();
}
@override
Widget build(BuildContext context) {
params = ModalRoute.of(context)!.settings.arguments as GroupChatDetailedScreenParams;
data = Provider.of<ChatProviderModel>(context, listen: false);
// callPro = Provider.of<ChatCallProvider>(context, listen: false);
if (params != null) {
data.getGroupChatHistory(
params!.groupChatDetails!
// senderUID: AppState().chatDetails!.response!.id!.toInt(),
// receiverUID: params!.groupChatHistory!.groupId!,
// loadMore: false,
// isNewChat: params!.isNewChat!,
);
data.initAudio(receiverId: params!.groupChatDetails!.groupId!);
}
return Scaffold(
backgroundColor: MyColors.backgroundColor,
appBar: ChatAppBarWidget(
context,
title: params!.groupChatDetails!.groupName.toString().replaceAll(".", " ").capitalizeFirstofEach,
showHomeButton: false,
// showTyping: true,
// chatUser: params!.groupChatHistory!.groupChatHistoryTargetUserList as ChatUser,
actions: [
// SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() {
// makeCall(callType: "AUDIO");
// }),
// 24.width,
// SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() {
// makeCall(callType: "VIDEO");
// }),
// 21.width,
],
),
body: SafeArea(
child: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return (m.isLoading
? ChatHomeShimmer(
isDetailedScreen: true,
)
: Column(
children: <Widget>[
SmartRefresher(
enablePullDown: false,
enablePullUp: true,
onLoading: () {
getMoreChat();
},
header: const MaterialClassicHeader(
color: MyColors.gradiantEndColor,
),
controller: _rc,
reverse: true,
child: ListView.separated(
controller: m.scrollController,
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
reverse: true,
itemCount: m.groupChatHistory.length,
padding: const EdgeInsets.all(21),
separatorBuilder: (BuildContext cxt, int index) => 8.height,
itemBuilder: (BuildContext context, int i) {
return SwipeTo(
iconColor: MyColors.lightGreenColor,
child: GroupChatBubble(
dateTime: m.groupChatHistory[i].createdDate!,
cItem: m.groupChatHistory[i],
),
onRightSwipe: () {
// m.chatReply(
// m.groupChatHistory[i],
// );
},
).onPress(() async {
logger.w(m.userChatHistory[i].toJson());
if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) {
if (m.userChatHistory[i].fileTypeId! == 1 ||
m.userChatHistory[i].fileTypeId! == 5 ||
m.userChatHistory[i].fileTypeId! == 7 ||
m.userChatHistory[i].fileTypeId! == 6 ||
m.userChatHistory[i].fileTypeId! == 8
// || m.userChatHistory[i].fileTypeId! == 2
) {
m.getChatMedia(context,
fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!);
}
}
});
},
),
).expanded,
if (m.isReplyMsg)
SizedBox(
height: 82,
child: Row(
children: <Widget>[
Container(height: 82, color: MyColors.textMixColor, width: 6),
Container(
color: MyColors.darkTextColor.withOpacity(0.10),
padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString()
? "You"
: m.repliedMsg.first.currentUserName.toString().replaceAll(".", " "))
.toText14(color: MyColors.lightGreenColor),
(m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2)
],
).expanded,
12.width,
if (m.isReplyMsg && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m),
12.width,
const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe),
],
),
).expanded,
],
),
),
if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg")
SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21),
const Divider(height: 1, color: MyColors.lightGreyEFColor),
if (m.isRecoding)
Column(
children: <Widget>[
Row(
children: [
Text(m.buildTimer()).paddingAll(10),
if (m.isRecoding && m.isPlaying)
WaveBubble(
playerController: m.playerController,
isPlaying: m.playerController.playerState == PlayerState.playing,
onTap: () {},
).expanded
else
AudioWaveforms(
waveStyle: const WaveStyle(
waveColor: MyColors.lightGreenColor,
middleLineColor: Colors.transparent,
extendWaveform: true,
showBottom: true,
showTop: true,
waveThickness: 2,
showMiddleLine: false,
middleLineThickness: 0,
),
padding: const EdgeInsets.all(5),
shouldCalculateScrolledPosition: false,
margin: EdgeInsets.zero,
size: const Size(double.infinity, 30.0),
recorderController: m.recorderController,
backgroundColor: Colors.white,
).expanded,
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Icon(
Icons.delete_outlined,
size: 26,
color: MyColors.lightGreenColor,
).paddingAll(10).onPress(() {
m.deleteRecoding();
}),
SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26)
.onPress(
() => m.sendChatMessage(context,
targetUserId: params!.groupChatDetails!.groupId!,
userStatus: 0,
userEmail: "",
targetUserName: params!.groupChatDetails!.groupName!),
)
.paddingOnly(right: 21),
],
),
],
).objectContainerView(disablePadding: true, radius: 0),
if (!m.isRecoding)
Row(
children: [
CustomAutoDirection(
onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL),
text: m.msgText,
child: TextField(
// textDirection: m.textDirection,
controller: m.message,
decoration: InputDecoration(
hintTextDirection: m.textDirection,
hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(),
hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
filled: true,
fillColor: MyColors.white,
contentPadding: const EdgeInsets.only(
left: 21,
top: 20,
bottom: 20,
),
prefixIconConstraints: const BoxConstraints(),
prefixIcon: m.sFileType.isNotEmpty
? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15)
: null,
),
onChanged: (String val) {
m.inputBoxDirection(val);
m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.groupChatDetails!.groupId!);
},
).expanded,
),
if (m.sFileType.isNotEmpty)
Row(
children: <Widget>[
const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5),
("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0),
],
).onPress(() => m.removeAttachment()).paddingOnly(right: 15),
if (m.sFileType.isEmpty)
RotationTransition(
turns: const AlwaysStoppedAnimation(45 / 360),
child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress(
() => m.selectImageToUpload(context),
),
).paddingOnly(right: 15),
const Icon(
Icons.mic,
color: MyColors.lightGreenColor,
).paddingOnly(right: 15).onPress(() {
m.startRecoding(context);
}),
SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26)
.onPress(
() =>m.sendGroupChatMessage(context,
targetUserId: params!.groupChatDetails!.groupId!,
userStatus: 0,
userEmail: "",
targetUserName: params!.groupChatDetails!.groupName!),
)
.paddingOnly(right: 21),
],
).objectContainerView(disablePadding: true, radius: 0),
],
));
},
),
),
);
}
Widget showReplyImage(List<SingleUserChatModel> data, ChatProviderModel m) {
if (data.first.isImageLoaded! && data.first.image != null) {
return Container(
width: 43,
height: 43,
decoration: BoxDecoration(
border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)),
);
} else {
return data.first.fileTypeResponse != null && data.first.fileTypeResponse!.fileTypeName != null
? Container(
width: 43,
height: 43,
constraints: const BoxConstraints(),
decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white),
child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName ?? ""), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5))
: const SizedBox();
}
}
void makeCall({required String callType}) async {
callPro.initCallListeners();
print("================== Make call Triggered ============================");
// Map<String, dynamic> json = {
// "callerID": AppState().chatDetails!.response!.id!.toString(),
// "callerDetails": AppState().chatDetails!.toJson(),
// "receiverID": params!.chatUser!.id.toString(),
// "receiverDetails": params!.chatUser!.toJson(),
// "title": params!.chatUser!.userName!.replaceAll(".", " "),
// "calltype": callType == "VIDEO" ? "Video" : "Audio",
// };
logger.w(json);
// CallDataModel callData = CallDataModel.fromJson(json);
// await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) => OutGoingCall(
// isVideoCall: callType == "VIDEO" ? true : false,
// outGoingCallData: callData,
// ),
// ),
// ).then((value) {
// print("then");
// callPro.stopListeners();
// });
}
}

@ -0,0 +1,131 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart';
import 'package:provider/provider.dart';
class GroupMembersScreen extends StatefulWidget {
const GroupMembersScreen({Key? key,}) : super(key: key);
@override
State<GroupMembersScreen> createState() => _GroupMembersScreenState();
}
class _GroupMembersScreenState extends State<GroupMembersScreen> {
late ChatProviderModel provider;
late List<GroupUserList> groupUserList;
@override
void initState() {
super.initState();
provider = Provider.of<ChatProviderModel>(context, listen: false);
}
@override
Widget build(BuildContext context) {
groupUserList = ModalRoute.of(context)!.settings.arguments as List<GroupUserList>;
return Scaffold(
backgroundColor: MyColors.white,
appBar: ChatAppBarWidget(
context,
title: LocaleKeys.groupMembers.tr(),
showHomeButton: false,
),
body:
groupUserList!.isNotEmpty ? ListView.separated(
itemCount: groupUserList!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.only(bottom: 5.0),
itemBuilder: (BuildContext context, int index) {
if(groupUserList![index].id != AppState().chatDetails!.response!.id) {
return SizedBox(
height: 55,
child: Row(
children: [
Stack(
children: <Widget>[
if (groupUserList![index].image == null)
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color:groupUserList![index].userStatus == 1
? MyColors.green2DColor
: Colors.red,
),
).circle(10),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(groupUserList![index].userName! ?? "").toText14(
color: MyColors.darkTextColor).paddingOnly(
left: 11, top: 13),
],
).expanded,
Row(
children: [
IconButton(onPressed: (){
goToChat(groupUserList![index]);
}, icon: Icon(Icons.chat))
],
)
],
),
);
} else {
return const SizedBox();
}
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(color: MyColors.lightGreyE5Color).paddingOnly(
left: 70),
).paddingAll(10)
: Column(
children: <Widget>[
Utils
.getNoDataWidget(context)
.expanded,
],
)
);
}
void goToChat(GroupUserList groupUser){
ChatUser chatUser = ChatUser.fromJson(groupUser.toJson());
Navigator.pushNamed(context,
AppRoutes.chatDetailed,
arguments:
ChatDetailedScreenParams(
chatUser,
false));
}
}

@ -0,0 +1,142 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart';
import 'package:provider/provider.dart';
class ManageGroupScreen extends StatefulWidget {
const ManageGroupScreen({
Key? key,
}) : super(key: key);
@override
State<ManageGroupScreen> createState() => _ManageGroupScreenState();
}
class _ManageGroupScreenState extends State<ManageGroupScreen> {
late ChatProviderModel provider;
GroupResponse? groupDetails;
@override
void initState() {
super.initState();
provider = Provider.of<ChatProviderModel>(context, listen: false);
}
@override
Widget build(BuildContext context) {
groupDetails = ModalRoute.of(context)!.settings.arguments as GroupResponse;
return Scaffold(
backgroundColor: MyColors.white,
appBar: ChatAppBarWidget(
context,
title: LocaleKeys.manageGroup.tr(),
showHomeButton: false,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
LocaleKeys.admin
.tr()
.toText14(color: MyColors.darkTextColor)
.paddingOnly(right: 25)!,
groupDetails!.groupUserList!.isNotEmpty
? ListView.separated(
itemCount: groupDetails!.groupUserList!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.only(bottom: 5.0),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: Row(
children: [
Stack(
children: <Widget>[
if (groupDetails!.groupUserList![index].image ==
null)
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: groupDetails!.groupUserList![index]
.userStatus ==
1
? MyColors.green2DColor
: Colors.red,
),
).circle(10),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(groupDetails!
.groupUserList![index].userName! ??
"")
.toText14(color: MyColors.darkTextColor)
.paddingOnly(left: 11, top: 13),
],
).expanded,
Row(
children: [
Switch(
value: groupDetails!
.groupUserList![index].isAdmin!,
onChanged: groupDetails!
.groupUserList![index].id ==
AppState().chatDetails!.response!.id
? null
: (value) {
setState(() {
groupDetails!.groupUserList![index]
.isAdmin = value;
updateGroupAdmin(
groupDetails!.groupUserList!,
groupDetails!.groupId);
});
},
)
],
)
],
),
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(color: MyColors.lightGreyE5Color)
.paddingOnly(left: 70),
).paddingAll(10)
: Column(
children: <Widget>[
Utils.getNoDataWidget(context).expanded,
],
)
],
));
}
void updateGroupAdmin(List<GroupUserList> groupUserList, int? groupId) async {
//Group id need to be updated..
provider.updateGroupAdmin(groupId, groupUserList);
}
}

@ -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

@ -16,8 +16,8 @@ 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/offers_and_discounts/get_offers_list.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.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/ui/landing/widget/app_drawer.dart';
@ -26,6 +26,7 @@ import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_banner.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart';
import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart';
@ -62,7 +63,9 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
data = Provider.of<DashboardProviderModel>(context, listen: false);
marathonProvider = Provider.of<MarathonProvider>(context, listen: false);
cProvider = Provider.of<ChatProviderModel>(context, listen: false);
_bHubCon();
if (checkIfPrivilegedForChat()) {
_bHubCon();
}
_onRefresh(true);
});
}
@ -76,11 +79,8 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
void checkSession() async {
try {
Utils.showLoading(context);
await DashboardApiClient().getOpenMissingSwipes();
Utils.hideLoading(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
@ -89,24 +89,28 @@ class _DashboardScreenState extends State<DashboardScreen> 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!);
});
}
}
});
}
@ -142,54 +146,42 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
data.fetchMenuEntries();
data.getCategoryOffersListAPI(context);
marathonProvider.getMarathonDetailsFromApi();
if (!isFromInit) checkHubCon();
if (isFromInit) {
checkERMChannel();
}
if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon();
_refreshController.refreshCompleted();
}
void checkERMChannel() {
data.getITGNotification().then((val) {
if (val!.result!.data != null) {
print("-------------------- Survey ----------------------------");
if (val.result!.data!.notificationType == "Survey") {
Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data);
} else {
print("------------------------------------------- Ads --------------------");
DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(
(value) {
if (value!.mohemmItgResponseItem!.statusCode == 200) {
if (value.mohemmItgResponseItem!.result!.data != null) {
Navigator.pushNamed(context, AppRoutes.advertisement, arguments: {
"masterId": val.result!.data!.notificationMasterId,
"advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement,
});
}
}
},
);
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
// appBar: AppBar(
// actions: [
// IconButton(
// onPressed: () {
// data.getITGNotification().then((val) {
// if (val!.result!.data != null) {
// print("-------------------- Survey ----------------------------");
// if (val.result!.data!.notificationType == "Survey") {
// Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data);
// } else {
// print("------------------------------------------- Ads --------------------");
// DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(
// (value) {
// if (value!.mohemmItgResponseItem!.statusCode == 200) {
// if (value.mohemmItgResponseItem!.result!.data != null) {
// Navigator.pushNamed(context, AppRoutes.advertisement, arguments: {
// "masterId": val.result!.data!.notificationMasterId,
// "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement,
// });
//
// // Navigator.push(
// // context,
// // MaterialPageRoute(
// // builder: (BuildContext context) => ITGAdsScreen(
// // addMasterId: val.result!.data!.notificationMasterId!,
// // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!,
// // ),
// // ),
// // );
// }
// }
// },
// );
// }
// }
// });
// },
// icon: Icon(Icons.add))
// ],
// ),
body: Column(
children: [
Row(
@ -250,7 +242,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color),
(AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true),
16.height,
@ -343,7 +335,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0),
),
),
child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/attendance.svg" : "assets/images/attendance.svg"),
child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/biometrics.svg" : "assets/images/biometrics.svg"),
).onPress(() {
showMyBottomSheet(
context,
@ -448,7 +440,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!,
transitionOnUserGestures: true,
child: Image.network(
data.getOffersList[index].bannerImage!,
data.getOffersList[index].logo ?? "",
fit: BoxFit.contain,
),
),
@ -558,20 +550,28 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
children: [
SvgPicture.asset(
"assets/icons/chat/chat.svg",
color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color,
color: !checkIfPrivilegedForChat()
? MyColors.lightGreyE3Color
: currentIndex == 4
? MyColors.grey3AColor
: cProvider.disbaleChatForThisUser
? MyColors.lightGreyE3Color
: MyColors.grey98Color,
).paddingAll(4),
Consumer<ChatProviderModel>(
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),
),
);
return !checkIfPrivilegedForChat()
? const SizedBox()
: 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),
),
);
},
),
],
@ -595,7 +595,9 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
} else if (index == 3) {
Navigator.pushNamed(context, AppRoutes.itemsForSale);
} else if (index == 4) {
Navigator.pushNamed(context, AppRoutes.chat);
if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) {
Navigator.pushNamed(context, AppRoutes.chat);
}
}
},
),
@ -618,7 +620,17 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
}
}
});
Navigator.pushNamed(context, AppRoutes.offersAndDiscountsDetails, arguments: getOffersDetailList);
}
bool checkIfPrivilegedForChat() {
for (PrivilegeListModel element in AppState().privilegeListModel!) {
if (element.serviceName?.toLowerCase() == "chat") {
if (element.previlege != null) {
return element.previlege!;
}
}
}
return false;
}
}

@ -2,10 +2,17 @@ import 'dart:convert';
import 'dart:io' as Io;
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:flutter_countdown_timer/index.dart';
import 'package:lottie/lottie.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/lottie_consts.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads;
import 'package:path_provider/path_provider.dart';
@ -24,11 +31,13 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
bool skip = false;
bool isVideo = false;
bool isImage = false;
bool isAudio = false;
String ext = '';
late File imageFile;
ads.Advertisement? advertisementData;
dynamic data;
String? masterID;
int videoDuration = 0;
void checkFileType() async {
String? rFile = advertisementData!.viewAttachFileColl!.first.base64String;
@ -38,11 +47,13 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
await processImage(rFile!);
isImage = true;
} else {
if (ext == ".aac") {
isAudio = true;
}
isVideo = true;
_futureController = createVideoPlayer(rFile!);
}
setState(() {});
initTimer();
}
Future processImage(String encodedBytes) async {
@ -76,26 +87,29 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
void initTimer() {
Future.delayed(const Duration(seconds: 5), () {
skip = true;
setState(() {});
// setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
if (_controller != null) _controller.dispose();
// player.stop();
// player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
data = ModalRoute.of(context)!.settings.arguments;
if (advertisementData == null) advertisementData = data["advertisement"] as ads.Advertisement;
if (masterID == null) masterID = data["masterId"];
advertisementData ??= data["advertisement"] as ads.Advertisement;
masterID ??= data["masterId"];
if (advertisementData != null) {
checkFileType();
videoDuration = advertisementData?.durationInSeconds ?? 0;
}
// double height = MediaQuery.of(context).size.height * .25;
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: [
if (isVideo)
@ -104,11 +118,52 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
builder: (BuildContext context, AsyncSnapshot<Object?> snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) {
_controller = snapshot.data as VideoPlayerController;
return Positioned.fill(
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
),
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: isAudio
? Lottie.asset(MyLottieConsts.audioPlaybackLottie)
: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
),
),
30.height,
CountdownTimer(
endTime: DateTime.now().millisecondsSinceEpoch + 1000 * videoDuration,
onEnd: null,
endWidget: "00:00:00".toText14(color: Colors.white, isBold: true),
textStyle: const TextStyle(color: Colors.white, fontSize: 16, letterSpacing: -0.48, fontWeight: FontWeight.bold),
),
50.height,
Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor))
.onPress(() {
try {
DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!).then((value) {
logger.d(value);
Navigator.pop(context);
});
} catch (ex) {
logger.wtf(ex);
Utils.handleException(ex, context, null);
}
}),
// DefaultButton(LocaleKeys.home.tr(), () async {
// DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!).then((value) {
// logger.d(value);
// });
// }).paddingOnly(left: 50, right: 50)
// ElevatedButton(
// onPressed: () async {
// // DashboardApiClient().setAdvertisementViewed(widget.addMasterId, widget.advertisement!.advertisementId!).then((value) {
// // logger.d(value);
// // });
// },
// child: const Text("Go To Dashboard"),
// )
],
);
} else {
return const Center(
@ -117,16 +172,28 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
}
},
),
if (isImage) Image.file(imageFile),
if (skip)
ElevatedButton(
onPressed: () async {
// DashboardApiClient().setAdvertisementViewed(widget.addMasterId, widget.advertisement!.advertisementId!).then((value) {
// logger.d(value);
// });
},
child: const Text("Go To Dashboard"),
)
if (isImage)
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.file(imageFile),
50.height,
Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)).onPress(
() {
try {
DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!).then((value) {
logger.d(value);
Navigator.pop(context);
});
} catch (ex) {
logger.wtf(ex);
Utils.handleException(ex, context, null);
}
},
),
],
),
],
),
);

@ -72,7 +72,7 @@ class _SurveyScreenState extends State<SurveyScreen> {
],
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
39.height,
LocaleKeys.rateUI.tr().toText16(),
LocaleKeys.rateUI2.tr().toText16(),
10.height,
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7),
@ -134,7 +134,7 @@ class _SurveyScreenState extends State<SurveyScreen> {
void performAPI() async {
Utils.showLoading(context);
try {
ItgMainRes? res= await DashboardApiClient().submitItgForm(
ItgMainRes? res = await DashboardApiClient().submitItgForm(
comment: reviewText,
masterId: itgResponseData!.notificationMasterId ?? "",
itgList: [
@ -144,15 +144,12 @@ class _SurveyScreenState extends State<SurveyScreen> {
serviceId: itgResponseData!.serviceId ?? 0);
Utils.hideLoading(context);
if(res!.mohemmItgResponseItem!.statusCode==200){
if (res!.mohemmItgResponseItem!.statusCode == 200) {
Utils.showToast("Survey has been submitted successfully");
Navigator.pop(context);
}else{
} else {
Utils.showToast(res.mohemmItgResponseItem!.message.toString());
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {

@ -96,7 +96,7 @@ class MenusWidget extends StatelessWidget {
Row(
children: [
Expanded(
child: data.leaveBalance.toString().toText16(color: Colors.white, isBold: true, maxlines: 1),
child: data.leaveBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1),
),
RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)),
],
@ -123,7 +123,7 @@ class MenusWidget extends StatelessWidget {
Row(
children: [
Expanded(
child: data.ticketBalance.toString().toText16(color: Colors.white, isBold: true, maxlines: 1),
child: data.ticketBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1),
),
RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)),
],

@ -3,11 +3,13 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:easy_localization/src/public_ext.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
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';
@ -19,16 +21,16 @@ 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';
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/button/hmg_connectivity_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:safe_device/safe_device.dart';
import 'package:wifi_iot/wifi_iot.dart';
class LoginScreen extends StatefulWidget {
@ -58,30 +60,33 @@ class _LoginScreenState extends State<LoginScreen> {
bool isOnExternalStorage = false;
bool isDevelopmentModeEnable = false;
// late HmsApiAvailability hmsApiAvailability;
@override
void initState() {
super.initState();
// hmsApiAvailability = HmsApiAvailability();
// checkFirebaseToken();
// if (kReleaseMode) {
// checkDeviceSafety();
// }
}
void checkDeviceSafety() async {
try {
isJailBroken = await SafeDevice.isJailBroken;
isRealDevice = await SafeDevice.isRealDevice;
if (Platform.isAndroid) {
isOnExternalStorage = await SafeDevice.isOnExternalStorage;
isDevelopmentModeEnable = await SafeDevice.isDevelopmentModeEnable;
}
if (isJailBroken || !isRealDevice || isOnExternalStorage || isDevelopmentModeEnable) {
Navigator.pushNamedAndRemoveUntil(context, AppRoutes.unsafeDeviceScreen, (_) => false);
}
} catch (error) {
print(error);
}
}
// void checkDeviceSafety() async {
// try {
// isJailBroken = await SafeDevice.isJailBroken;
// isRealDevice = await SafeDevice.isRealDevice;
// if (Platform.isAndroid) {
// isOnExternalStorage = await SafeDevice.isOnExternalStorage;
// isDevelopmentModeEnable = await SafeDevice.isDevelopmentModeEnable;
// }
// if (isJailBroken || !isRealDevice || isOnExternalStorage || isDevelopmentModeEnable) {
// Navigator.pushNamedAndRemoveUntil(context, AppRoutes.unsafeDeviceScreen, (_) => false);
// }
// } catch (error) {
// print(error);
// }
// }
@override
void dispose() {
@ -94,25 +99,50 @@ class _LoginScreenState extends State<LoginScreen> {
Future<void> checkFirebaseToken() async {
try {
Utils.showLoading(context);
await Firebase.initializeApp();
_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 {
if (!(await Utils.isGoogleServicesAvailable())) {
print("HUAWEI APPPP GALLERYYYY!!!!");
AppState().setIsHuawei = true;
AppNotifications().initHuaweiPush(checkLoginInfo);
} else {
print("GOOGLE PLAY STOREEEE!!!!");
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
checkLoginInfo();
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
// });
} 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();
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
}
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();
}
}
@ -159,15 +189,14 @@ class _LoginScreenState extends State<LoginScreen> {
}
}
@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@12345";
// username.text = "15153"; // Tamer User
// password.text = "Abcd@12345";
// username.text = "206535"; // Hashim User
// password.text = "Namira786";
@ -192,7 +221,9 @@ class _LoginScreenState extends State<LoginScreen> {
children: [
Row(
children: [
Expanded(child: SizedBox()),
// Expanded(
// child:SizedBox(child: HmgConnectivityButton(),),
// ),
Row(
children: [
LocaleKeys.english.tr().toText14(color: AppState().isArabic(context) ? null : MyColors.textMixColor).onPress(() {

@ -324,20 +324,22 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
Future<void> performApiCall(String _title, String _icon, int _flag, int sendVerificationFlat, {bool isDirectLogin = false}) async {
try {
if (isDirectLogin)
if (isDirectLogin) {
setState(() {
Utils.showLoading(context);
});
else
} else {
Utils.showLoading(context);
}
await LoginApiClient().checkMobileAppVersion();
await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!);
if (!isDirectLogin)
if (!isDirectLogin) {
BasicMemberInformationModel? memberInformationModel =
await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType(0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName);
}
if (isDirectLogin) performDirectApiCall(_title, _icon, _flag, "", null);
if (!isDirectLogin) Utils.hideLoading(context);
if (!isDirectLogin)
if (!isDirectLogin) {
OtpDialog(
context,
sendVerificationFlat,
@ -353,6 +355,7 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
performApiCall(_title, _icon, _flag, sendVerificationFlat, isDirectLogin: isDirectLogin);
},
).displayDialog(context);
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
@ -361,7 +364,7 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
Future<void> 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,
@ -369,9 +372,10 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
_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 ?? [];
if (genericResponseModel.errorMessage != null) {
Utils.showToast(genericResponseModel.errorMessage ?? "");
// Navigator.pop(context);

@ -628,7 +628,7 @@ class _VerifyLoginScreenState extends State<VerifyLoginScreen> {
_flag,
AppState().memberLoginList?.pMOBILENUMBER ?? "",
AppState().getUserName!,
firebaseToken!,
AppState().getIsHuawei ? AppState().getHuaweiPushToken : firebaseToken!,
Platform.isAndroid ? "android" : "ios");
if (genericResponseModel?.errorMessage != null) {
Utils.showToast(genericResponseModel?.errorMessage ?? "");

@ -17,7 +17,18 @@ class MarathonIntroScreen extends StatelessWidget {
Widget build(BuildContext context) {
MarathonProvider provider = context.watch<MarathonProvider>();
return Scaffold(
appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()),
appBar: AppBarWidget(
context,
title: LocaleKeys.brainMarathon.tr(),
onHomeTapped: () {
Navigator.pop(context);
context.setLocale(provider.savedLocale);
},
onBackTapped: () {
Navigator.pop(context);
context.setLocale(provider.savedLocale);
},
),
body: Column(
children: <Widget>[
ListView(

@ -1,6 +1,7 @@
import 'dart:async';
import 'package:appinio_swiper/appinio_swiper.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/marathon/demo_marathon_repo.dart';
@ -31,7 +32,7 @@ class MarathonProvider extends ChangeNotifier {
int? selectedOptionIndex;
String? selectedOptionId;
int? totalQualifiers;
Locale savedLocale = const Locale("en", "US");
String? gapTimeImage;
String? gapTimeText;
int? gapTimeType;
@ -190,6 +191,7 @@ class MarathonProvider extends ChangeNotifier {
oneSec,
(Timer timer) async {
if (totalSecondsToWaitForMarathon == 0) {
timer.cancel();
if (isUserWaiting) {
MarathonApiClient().joinMarathonAsParticipant().whenComplete(() async {
await callNextQuestionApi();
@ -197,7 +199,6 @@ class MarathonProvider extends ChangeNotifier {
} else {
isButtonEnabled = false;
}
timer.cancel();
return;
} else {
totalSecondsToWaitForMarathon--;
@ -210,20 +211,24 @@ class MarathonProvider extends ChangeNotifier {
int totalCurrentQuestionTime = 0;
int currentGapTime = 0;
Timer timerForQuestion = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
int callCountThreshold = 0;
void startTimerForQuestion() {
const Duration oneSec = Duration(seconds: 1);
timerForQuestion = Timer.periodic(
oneSec,
(Timer timer) async {
// This 2 is just to show the color of answer tile for 1 and then update card status
if (totalCurrentQuestionTime - currentGapTime == 1) {
getCorrectAnswerAndUpdateAnswerColor();
// This 1 is just to show the color of answer tile for 1 and then update card status
if (totalCurrentQuestionTime - currentGapTime == 0) {
if (callCountThreshold == 0) {
getCorrectAnswerAndUpdateAnswerColor();
}
}
if (totalCurrentQuestionTime - currentGapTime == -2) {
updateCardStatusToAnswer();
if (callCountThreshold == 0) {
updateCardStatusToAnswer();
}
// scheduleMicrotask(() async {
// if (AppState().getIsDemoMarathon || isUserOutOfGame) {
// await callNextQuestionApi();
@ -243,6 +248,7 @@ class MarathonProvider extends ChangeNotifier {
notifyListeners();
}
totalCurrentQuestionTime--;
callCountThreshold = 0;
}
if (totalCurrentQuestionTime == 0) {
@ -255,6 +261,7 @@ class MarathonProvider extends ChangeNotifier {
} else {
if (totalCurrentQuestionTime - currentGapTime != -2) {
totalCurrentQuestionTime--;
callCountThreshold = 0;
}
}
@ -272,8 +279,8 @@ class MarathonProvider extends ChangeNotifier {
oneSec,
(Timer timer) async {
if (totalSecondsToWaitForWinner == 1) {
await callGetSelectedWinnersApi().whenComplete(() => updateQuestionCardStatus(QuestionCardStatus.winnerFound));
timer.cancel();
await callGetSelectedWinnersApi().whenComplete(() => updateQuestionCardStatus(QuestionCardStatus.winnerFound));
return;
} else if (totalSecondsToWaitForWinner == 15) {
totalSecondsToWaitForWinner--;
@ -289,6 +296,18 @@ class MarathonProvider extends ChangeNotifier {
//************************************************ FUNCTIONS **********************************************************
void updateLanguageAsPerMarathon(BuildContext context, MarathonDetailModel detailModel) {
savedLocale = context.locale;
if (detailModel.selectedLanguage == 1) {
context.setLocale(const Locale("en", "US"));
} else if (detailModel.selectedLanguage == 2) {
context.setLocale(const Locale("ar", "SA"));
} else if (detailModel.selectedLanguage == 3) {
} else {
context.setLocale(const Locale("en", "US"));
}
}
Future<bool> callSubmitOptionApi() async {
return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId);
}
@ -334,11 +353,15 @@ class MarathonProvider extends ChangeNotifier {
gapTimeImage = currentQuestion.gapImage;
gapTimeText = currentQuestion.gapText;
gapTimeType = currentQuestion.gapType;
startTimerForQuestion();
updateCardData();
if (Utils.isLoading) {
Utils.hideLoading(AppRoutes.navigatorKey.currentContext!);
}
startTimerForQuestion();
updateCardData();
if (!AppState().getIsDemoMarathon) {
totalMarathoners = await MarathonApiClient().getMarathonersCount(marathonId: marathonDetailModel.id!);
}
Navigator.pushReplacementNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.marathonScreen);
} else {
currentQuestion = AppState().getIsDemoMarathon
@ -413,6 +436,7 @@ class MarathonProvider extends ChangeNotifier {
}
void getCorrectAnswerAndUpdateAnswerColor() {
callCountThreshold = 1;
if (selectedOptionIndex != null) {
scheduleMicrotask(() async {
if (AppState().getIsDemoMarathon) {
@ -447,7 +471,7 @@ class MarathonProvider extends ChangeNotifier {
if (currentQuestionNumber == 0) {
return;
}
callCountThreshold = 1;
scheduleMicrotask(() async {
await callNextQuestionApi();
});
@ -478,6 +502,7 @@ class MarathonProvider extends ChangeNotifier {
void resetValues() async {
_currentQuestionNumber = 0;
iAmWinner = false;
cardContentList.clear();
itsMarathonTime = false;
timerForWinnerSelection.cancel();
@ -502,6 +527,7 @@ class MarathonProvider extends ChangeNotifier {
answerStatusesList[i] = QuestionCardStatus.question;
}
}
AppRoutes.navigatorKey.currentContext!.setLocale(savedLocale);
notifyListeners();
}

@ -78,7 +78,12 @@ class MarathonScreen extends StatelessWidget {
16.height,
Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.demoMarathonDetailModel.selectedLanguage!,
arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr!,
englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!,
).toText22(
color: MyColors.grey3AColor,
isCentered: true,
),
@ -92,7 +97,12 @@ class MarathonScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color),
(AppState().isArabic(context) ? provider.demoMarathonDetailModel.sponsors!.first.nameAr ?? "" : provider.demoMarathonDetailModel.sponsors!.first.nameEn ?? "").toText14(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.demoMarathonDetailModel.selectedLanguage!,
englishContent: provider.demoMarathonDetailModel.sponsors!.first.nameEn!,
arabicContent: provider.demoMarathonDetailModel.sponsors!.first.nameAr!,
).toText14(
color: MyColors.darkTextColor,
isBold: true,
),
@ -160,7 +170,12 @@ class MarathonScreen extends StatelessWidget {
provider.iAmWinner
? Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
).toText24(
color: MyColors.grey3AColor,
isCentered: true,
),
@ -169,26 +184,46 @@ class MarathonScreen extends StatelessWidget {
],
)
: const SizedBox(),
36.height,
if (provider.selectedWinners != null) ...<Widget>[
ListView.separated(
shrinkWrap: true,
itemCount: provider.selectedWinners!.length,
separatorBuilder: (BuildContext context, int index) {
return const Divider();
},
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16(
color: MyColors.grey3AColor,
),
provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color),
],
);
},
),
provider.selectedWinners!.length == 1 && !provider.iAmWinner
? Column(
children: <Widget>[
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
arabicContent: provider.selectedWinners![0].nameAr ?? "",
englishContent: provider.selectedWinners![0].nameEn ?? "",
).toText24(
color: MyColors.grey3AColor,
isCentered: true,
),
8.height,
provider.selectedWinners![0].employeeId!.toText22(color: MyColors.grey57Color),
],
)
: ListView.separated(
shrinkWrap: true,
itemCount: provider.selectedWinners!.length,
separatorBuilder: (BuildContext context, int index) {
return const Divider();
},
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
arabicContent: provider.selectedWinners![index].nameAr ?? "",
englishContent: provider.selectedWinners![index].nameEn ?? "",
).toText16(
color: MyColors.grey3AColor,
),
provider.selectedWinners![index].employeeId!.toText16(color: MyColors.grey57Color),
],
);
},
),
],
60.height,
if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[
@ -196,7 +231,12 @@ class MarathonScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color),
(AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage!,
arabicContent: provider.marathonDetailModel.sponsors!.first.nameAr ?? "",
englishContent: provider.marathonDetailModel.sponsors!.first.nameEn ?? "",
).toText14(
color: MyColors.darkTextColor,
isBold: true,
),
@ -221,7 +261,7 @@ class MarathonScreen extends StatelessWidget {
);
}
Widget getNameContainer(BuildContext context) {
Widget getNameContainer(BuildContext context, MarathonProvider provider) {
return Container(
height: 50,
padding: const EdgeInsets.symmetric(horizontal: 20),
@ -233,8 +273,12 @@ class MarathonScreen extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!)
.toText17(isBold: true, color: MyColors.white),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: (!AppState().getIsDemoMarathon ? provider.marathonDetailModel.selectedLanguage : provider.demoMarathonDetailModel.selectedLanguage) ?? 0,
arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
).toText17(isBold: true, color: MyColors.white),
AppState().memberInformationList!.eMPLOYEENUMBER!.toText17(isBold: true, color: MyColors.white),
],
),
@ -299,8 +343,8 @@ class MarathonScreen extends StatelessWidget {
else ...<Widget>[
MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21),
],
if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...<Widget>[
getNameContainer(context),
if (provider.questionCardStatus == QuestionCardStatus.findingWinner && !provider.isUserOutOfGame) ...<Widget>[
getNameContainer(context, provider),
],
QuestionCardBuilder(
onQuestion: (BuildContext context) => const QuestionCard(),
@ -326,7 +370,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),
),

@ -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;
});
// });
}
}

@ -347,7 +347,10 @@ class MarathonBanner extends StatelessWidget {
@override
Widget build(BuildContext context) {
MarathonProvider provider = context.read<MarathonProvider>();
// if(provider.isUserWaiting) {
// provider.isUserWaiting = false;
// provider.getMarathonDetailsFromApi();
// }
return !provider.isPrivilegedWithMarathon
? getUnPrivilegedMarathon(context)
: provider.isUpComingMarathon
@ -431,7 +434,12 @@ class MarathonBanner extends StatelessWidget {
),
Flexible(
child: Text(
(AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "").trimString(15),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
englishContent: provider.marathonDetailModel.titleEn ?? "",
arabicContent: provider.marathonDetailModel.titleAr ?? "",
),
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontStyle: FontStyle.italic,
@ -522,7 +530,6 @@ class MarathonBanner extends StatelessWidget {
],
).onPress(() async {
int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes;
if (remainingTimeInMinutes > 5 && provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) {
Utils.showLoading(context);
try {
@ -541,6 +548,7 @@ class MarathonBanner extends StatelessWidget {
} else {
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
}
provider.updateLanguageAsPerMarathon(context, provider.isUpComingMarathon ? provider.marathonDetailModel : provider.demoMarathonDetailModel);
}),
)
: getNoUpcomingMarathonWidget(context);

@ -39,11 +39,23 @@ class MarathonDetailsCard extends StatelessWidget {
),
7.height,
LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? marathonDetailModel.titleAr : marathonDetailModel.titleEn}".toText20(color: MyColors.textMixColor, isBold: true),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: marathonDetailModel.titleEn ?? "",
arabicContent: marathonDetailModel.titleAr ?? "",
).toText20(color: MyColors.textMixColor, isBold: true),
Row(
children: <Widget>[
Flexible(
child: "${AppState().isArabic(context) ? marathonDetailModel.descAr : marathonDetailModel.descEn}".toText14(color: MyColors.grey77Color),
child: displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: marathonDetailModel.descEn ?? "",
arabicContent: marathonDetailModel.descAr ?? "",
).toText14(
color: MyColors.grey77Color,
),
)
],
),
@ -57,18 +69,22 @@ class MarathonDetailsCard extends StatelessWidget {
child: SizedBox(
height: 30,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: marathonDetailModel.sponsors!.first.sponsorPrizes!.length,
itemBuilder: (BuildContext context, int index) {
SponsorPrizes prizes = marathonDetailModel.sponsors!.first.sponsorPrizes![index];
return Container(
decoration: BoxDecoration(color: MyColors.backgroundColor, borderRadius: BorderRadius.circular(100), border: Border.all(color: MyColors.grey57Color.withOpacity(0.1))),
child: "${AppState().isArabic(context) ? prizes.marathonPrizeAr : prizes.marathonPrizeEn}"
.toText16(color: MyColors.greenColor, isBold: true)
.paddingOnly(left: 5, right: 5),
).paddingOnly(left: 5);
}),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: marathonDetailModel.sponsors!.first.sponsorPrizes!.length,
itemBuilder: (BuildContext context, int index) {
SponsorPrizes prizes = marathonDetailModel.sponsors!.first.sponsorPrizes![index];
return Container(
decoration: BoxDecoration(color: MyColors.backgroundColor, borderRadius: BorderRadius.circular(100), border: Border.all(color: MyColors.grey57Color.withOpacity(0.1))),
child: displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: prizes.marathonPrizeEn ?? "",
arabicContent: prizes.marathonPrizeAr ?? "",
).toText16(color: MyColors.greenColor, isBold: true).paddingOnly(left: 5, right: 5),
).paddingOnly(left: 5);
},
),
),
)
],
@ -77,7 +93,12 @@ class MarathonDetailsCard extends StatelessWidget {
Row(
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? marathonDetailModel.sponsors?.first.nameAr : marathonDetailModel.sponsors?.first.nameEn}".toText16(color: MyColors.darkTextColor, isBold: true),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: marathonDetailModel.sponsors?.first.nameEn ?? "",
arabicContent: marathonDetailModel.sponsors?.first.nameAr ?? "",
).toText16(color: MyColors.darkTextColor, isBold: true),
],
),
10.height,

@ -3,8 +3,6 @@ import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.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/ui/marathon/marathon_provider.dart';
import 'package:provider/provider.dart';
class MarathonHeader extends StatelessWidget {
const MarathonHeader({Key? key}) : super(key: key);

@ -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,

@ -85,7 +85,12 @@ class CardContent extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 15),
child: Text(
AppState().isArabic(context) ? "${provider.currentQuestion.titleAr}" ?? "" : provider.currentQuestion.titleEn ?? "",
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: (AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.selectedLanguage : provider.marathonDetailModel.selectedLanguage) ?? 0,
englishContent: provider.currentQuestion.titleEn ?? "",
arabicContent: provider.currentQuestion.titleAr ?? "",
),
style: const TextStyle(
color: MyColors.white,
fontSize: 16,
@ -125,7 +130,7 @@ class AnswerContent extends StatelessWidget {
return AnswerTileForText(
index: index,
onAnswerTapped: () {
if (provider.totalCurrentQuestionTime - provider.currentGapTime <= 1) {
if (provider.totalCurrentQuestionTime - provider.currentGapTime <= 0) {
null;
} else {
provider.updateCurrentQuestionOptionStatus(QuestionsOptionStatus.selected, index);
@ -170,9 +175,12 @@ class AnswerTileForText extends StatelessWidget {
alignment: Alignment.centerLeft,
decoration: MyDecorations.getAnswersContainerColor(provider.currentQuestion.questionOptions![index].optionStatus!),
child: Center(
child: (AppState().isArabic(context) ? provider.currentQuestion.questionOptions![index].titleAr! : provider.currentQuestion.questionOptions![index].titleEn!)
.toText16(color: provider.isUserOutOfGame ? MyColors.darkTextColor : getAnswerTextColor(provider.currentQuestion.questionOptions![index].optionStatus!))
.paddingOnly(top: 13, bottom: 13),
child: displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: (AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.selectedLanguage : provider.marathonDetailModel.selectedLanguage) ?? 0,
englishContent: provider.currentQuestion.questionOptions![index].titleEn ?? "",
arabicContent: provider.currentQuestion.questionOptions![index].titleAr ?? "",
).toText16(color: provider.isUserOutOfGame ? MyColors.darkTextColor : getAnswerTextColor(provider.currentQuestion.questionOptions![index].optionStatus!)).paddingOnly(top: 13, bottom: 13),
),
),
);

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
@ -71,27 +72,31 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
}
}
Future<List<Map<String, dynamic>>> addAttachments() async {
List<Map<String, dynamic>> list = [];
if (attachmentFiles.isNotEmpty) {
attachmentFiles.asMap().forEach((index, value) {
String type = attachmentFiles[index].path.split('.').last;
String name = attachmentFiles[index].path.split('/').last;
List<int> fileContent = value.readAsBytesSync();
String encodedFile = base64Encode(fileContent);
list.add(AttachmentModel(
attachmentID: index,
pFILECONTENTTYPE: type,
pFILENAME: name,
pFILEDATA: encodedFile,
pTRANSACTIONID: params!.transactionId,
).toJson());
});
}
return list;
}
void submitRequest() async {
try {
Utils.showLoading(context);
List<Map<String, dynamic>> list = [];
if (attachmentFiles.isNotEmpty) {
attachments.asMap().forEach((index, value) async {
String type = attachmentFiles[index].path.split('.').last;
String name = attachmentFiles[index].path.split('/').last;
// List<int> fileContent = await value.readAsBytes();
// String encodedFile = base64Encode(fileContent);
list.add(AttachmentModel(
attachmentID: index,
pFILECONTENTTYPE: type,
pFILENAME: name,
pFILEDATA: value,
pTRANSACTIONID: params!.transactionId,
).toJson());
});
}
List<Map<String, dynamic>> list = await addAttachments();
await MyAttendanceApiClient().addAttachment(list);
if (params!.approvalFlag == 'phone_numbers') {
await ProfileApiClient().startPhoneApprovalProcess(
"SUBMIT",

@ -67,8 +67,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
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);
}
}
}
@ -506,7 +506,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
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(
@ -517,7 +517,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
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 +576,9 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
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!);
@ -700,7 +700,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
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(

@ -159,7 +159,7 @@ class _ViewAttendanceState extends State<ViewAttendance> {
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<ViewAttendance> {
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<ViewAttendance> {
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(

@ -105,7 +105,7 @@ class _MonthlyPaySlipScreenState extends State<MonthlyPaySlipScreen> {
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 {

@ -238,7 +238,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
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(() {});
},
@ -298,7 +298,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
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(() {});
},
@ -357,7 +357,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
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(() {});
},

@ -88,8 +88,8 @@ class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
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),

@ -242,10 +242,10 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
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 +270,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
// 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 +294,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
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);

@ -233,10 +233,10 @@ class _DynamicInputScreenState extends State<DynamicInputScreenProfile> {
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<DynamicInputScreenProfile> {
// 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();

@ -18,7 +18,7 @@ import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/select_cat
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/button/simple_button.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
import 'package:mohem_flutter_app/widgets/image_picker.dart';
import 'package:mohem_flutter_app/widgets/image_picker.dart' as imagePicker;
import 'package:mohem_flutter_app/widgets/radio/show_radio.dart';
class AddItemDetailsFragment extends StatefulWidget {
@ -200,14 +200,22 @@ class _AddItemDetailsFragmentState extends State<AddItemDetailsFragment> {
children: [
title.toText16().expanded,
6.width,
SimpleButton(LocaleKeys.add.tr(), () {
ImageOptions.showImageOptionsNew(context, false, (String image, File file) {
setState(() {
images.add(image);
Navigator.of(context).pop();
});
});
}, fontSize: 14),
SimpleButton(
LocaleKeys.add.tr(),
() {
if (images.length < 3) {
imagePicker.ImageOptions.showImageOptionsNew(context, false, (String image, File file) {
setState(() {
images.add(image);
Navigator.of(context).pop();
});
});
} else {
Utils.showToast("The maximum no. of images allowed is 3.");
}
},
fontSize: 14,
),
],
),
if (images.isNotEmpty) 12.height,

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -98,9 +96,7 @@ class _ItemsForSaleFragmentState extends State<ItemsForSaleFragment> {
currentCategoryID == getSaleCategoriesList[index].categoryID ? const Icon(Icons.check_circle_rounded, color: MyColors.greenColor, size: 16.0) : Container(),
],
).expanded,
AppState().isArabic(context)
?getSaleCategoriesList[index].titleAr!.toText10()
:getSaleCategoriesList[index].title!.toText10()
AppState().isArabic(context) ? getSaleCategoriesList[index].titleAr!.toText10() : getSaleCategoriesList[index].title!.toText10()
],
).paddingOnly(left: 10, right: 10, bottom: 10, top: 12).expanded.objectContainerView(disablePadding: true),
),
@ -163,8 +159,8 @@ class _ItemsForSaleFragmentState extends State<ItemsForSaleFragment> {
aspectRatio: 148 / 127,
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.memory(
base64Decode(getItemsForSaleList.itemAttachments![0].content!),
child: Image.network(
getItemsForSaleList.itemAttachments![0].filePath!,
fit: BoxFit.cover,
),
),

@ -1,5 +1,4 @@
import 'dart:convert';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -24,6 +23,7 @@ class ItemForSaleDetailPage extends StatefulWidget {
class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
late GetItemsForSaleList getItemsForSaleList;
int _current = 0;
@override
Widget build(BuildContext context) {
@ -46,15 +46,32 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
transitionOnUserGestures: true,
child: AspectRatio(
aspectRatio: 322 / 261,
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.memory(
base64Decode(getItemsForSaleList.itemAttachments![0].content!),
fit: BoxFit.cover,
),
child: CarouselSlider(
items: getItemImages(),
options: CarouselOptions(
enableInfiniteScroll: false,
onPageChanged: (index, reason) {
setState(() {
_current = index;
});
}),
),
),
).paddingAll(8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: getItemImages().asMap().entries.map((entry) {
return Container(
width: 8.0,
height: 8.0,
margin: const EdgeInsets.symmetric(horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black).withOpacity(_current == entry.key ? 0.9 : 0.4),
),
);
}).toList(),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -88,22 +105,34 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
).expanded,
Row(
children: [
DefaultButton("Email", () async {
Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: getItemsForSaleList.emailAddress,
);
launchUrl(emailLaunchUri);
}, iconData: Icons.email_sharp, isTextExpanded: false)
DefaultButton(
"Email",
getItemsForSaleList.status == 'Approved'
? () async {
Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: getItemsForSaleList.emailAddress,
);
launchUrl(emailLaunchUri);
}
: null,
iconData: Icons.email_sharp,
isTextExpanded: false)
.expanded,
8.width,
DefaultButton("Call", () async {
Uri callLaunchUri = Uri(
scheme: 'tel',
path: getItemsForSaleList.mobileNumber,
);
launchUrl(callLaunchUri);
}, iconData: Icons.call_sharp, isTextExpanded: false)
DefaultButton(
"Call",
getItemsForSaleList.status == 'Approved'
? () async {
Uri callLaunchUri = Uri(
scheme: 'tel',
path: getItemsForSaleList.mobileNumber,
);
launchUrl(callLaunchUri);
}
: null,
iconData: Icons.call_sharp,
isTextExpanded: false)
.expanded,
],
).insideContainer,
@ -111,4 +140,23 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
),
);
}
List<Widget> getItemImages() {
List<Widget> itemImages = [];
getItemsForSaleList.itemAttachments!.forEach((element) {
itemImages.add(
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.network(
getItemsForSaleList.itemAttachments![0].filePath!,
fit: BoxFit.cover,
),
),
),
);
});
return itemImages;
}
}

@ -189,7 +189,7 @@ class _NewRequestState extends State<NewRequest> {
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 +200,7 @@ class _NewRequestState extends State<NewRequest> {
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 +211,16 @@ class _NewRequestState extends State<NewRequest> {
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(() {});

@ -85,7 +85,7 @@ class _OffersAndDiscountsDetailsState extends State<OffersAndDiscountsDetails> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
getOffersList[0].discount!.toText16(isBold: true),
getOffersList[0].discountDescription!.toText16(isBold: true),
InkWell(
onTap: () {
_shareOfferAsImage();

@ -107,8 +107,8 @@ class _EndEmploymentScreenState extends State<EndEmploymentScreen> {
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);
}
}
}

@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_mo_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart';
@ -18,8 +19,10 @@ class ItemHistoryScreenParams {
int? pItemId;
int? pPoHeaderId;
int? pOrgId;
bool isPRInfo;
GetPRInformationList? getPRInformationList;
ItemHistoryScreenParams({@required this.title, this.isItemHistory = true, this.isMO = true, this.pItemId, this.pPoHeaderId, this.pOrgId});
ItemHistoryScreenParams({@required this.title, this.isItemHistory = true, this.isMO = true, this.isPRInfo = false, this.getPRInformationList, this.pItemId, this.pPoHeaderId, this.pOrgId});
}
class ItemHistoryScreen extends StatefulWidget {
@ -51,7 +54,9 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
void loadData() {
if (_screenParams == null) {
_screenParams = ModalRoute.of(context)!.settings.arguments as ItemHistoryScreenParams;
getDataFromApi();
if (!_screenParams!.isPRInfo) {
getDataFromApi();
}
}
}
@ -86,15 +91,45 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
padding: const EdgeInsets.all(21),
physics: const BouncingScrollPhysics(),
children: [
if (_screenParams!.isPRInfo) prLinesDataView(),
if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(),
if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(),
if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData(),
if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty) Utils.getNoDataWidget(context),
if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty && !_screenParams!.isPRInfo) Utils.getNoDataWidget(context),
],
),
);
}
Widget prLinesDataView() {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cxt, index) => Column(
children: [
ItemDetailGrid(
ItemDetailViewCol("Cost Center", _screenParams!.getPRInformationList!.pRLines![index].cOSTCENTER ?? ""),
ItemDetailViewCol("Code", _screenParams!.getPRInformationList!.pRLines![index].iTEMCODE ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Unit", _screenParams!.getPRInformationList!.pRLines![index].uOM ?? ""),
ItemDetailViewCol("Price (SAR)", _screenParams!.getPRInformationList!.pRLines![index].uNITPRICE.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Amount (SAR)", _screenParams!.getPRInformationList!.pRLines![index].lINEAMOUNT.toString() ?? ""),
ItemDetailViewCol("Quantity", _screenParams!.getPRInformationList!.pRLines![index].qUANTITY.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("AMU (Last 3 months)", _screenParams!.getPRInformationList!.pRLines![index].iTEMAMU.toString() ?? ""),
Container(),
isItLast: true,
),
],
).objectContainerView(),
separatorBuilder: (cxt, index) => 12.height,
itemCount: _screenParams!.getPRInformationList!.pRLines!.length);
}
Widget loadMoItemHistoryData() {
return ListView.separated(
shrinkWrap: true,

@ -13,6 +13,7 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/wf_history_model.dart';
import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart';
import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart';
import 'package:mohem_flutter_app/ui/work_list/sheets/search_options_sheet.dart';
@ -29,8 +30,10 @@ class DelegateSheet extends StatefulWidget {
List<GetActionHistoryList>? actionHistoryList;
List<WFHistory>? wFHistory;
VoidCallback callBackFunc;
List<NotificationGetRespondAttributesList> getNotificationRespondAttributes;
DelegateSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory, required this.callBackFunc});
DelegateSheet(
{required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory, required this.callBackFunc, this.getNotificationRespondAttributes = const []});
@override
State<DelegateSheet> createState() => _DelegateSheetState();
@ -415,6 +418,7 @@ class _DelegateSheetState extends State<DelegateSheet> {
actionHistoryList: actionHistory,
notificationID: widget.notificationID,
isITGRequest: widget.wFHistory != null,
getNotificationRespondAttributes: widget.getNotificationRespondAttributes,
));
},
child: Row(
@ -489,6 +493,7 @@ class _DelegateSheetState extends State<DelegateSheet> {
favoriteReplacements: actionHistory,
notificationID: widget.notificationID,
isITGRequest: widget.wFHistory != null,
getNotificationRespondAttributes: widget.getNotificationRespondAttributes,
));
},
child: Row(
@ -555,6 +560,7 @@ class _DelegateSheetState extends State<DelegateSheet> {
replacementList: actionHistory,
notificationID: widget.notificationID,
isITGRequest: widget.wFHistory != null,
getNotificationRespondAttributes: widget.getNotificationRespondAttributes,
));
},
child: Row(

@ -10,10 +10,12 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart';
import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/dialogs/accept_reject_input_dialog.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
class SelectedItemSheet extends StatelessWidget {
@ -23,10 +25,18 @@ class SelectedItemSheet extends StatelessWidget {
GetFavoriteReplacements? favoriteReplacements;
ReplacementList? replacementList;
MemberInformationListModel? memberInformationListModel;
List<NotificationGetRespondAttributesList> getNotificationRespondAttributes;
bool isITGRequest;
SelectedItemSheet(this.title, {required this.apiMode, this.notificationID, this.actionHistoryList, this.favoriteReplacements, this.replacementList, this.isITGRequest = false});
SelectedItemSheet(this.title,
{required this.apiMode,
this.notificationID,
this.actionHistoryList,
this.favoriteReplacements,
this.replacementList,
this.isITGRequest = false,
this.getNotificationRespondAttributes = const []});
TextEditingController username = TextEditingController();
String comment = "";
@ -103,7 +113,7 @@ class SelectedItemSheet extends StatelessWidget {
email = replacementList!.emailAddress;
userId = replacementList!.userName;
}
isITGRequest ? performITGNetworkCall(context, email: email ?? "", userId: userId ?? "") : performNetworkCall(context, email: email ?? "", userId: userId ?? "");
isITGRequest ? performITGNetworkCall(context, email: email ?? "", userId: userId ?? "") : askForConfirmation(context, email: email ?? "", userId: userId ?? "");
} else {
Utils.showToast("Please enter comments");
}
@ -121,6 +131,41 @@ class SelectedItemSheet extends StatelessWidget {
);
}
void askForConfirmation(BuildContext context, {String? email, String? userId}) {
NotificationGetRespondAttributesList? notificationNoteInput;
NotificationGetRespondAttributesList? forwardToUser;
List<NotificationGetRespondAttributesList> filtered = getNotificationRespondAttributes.where((element) => element.attributeName == "NOTE" || element.attributeName == "WF_NOTE").toList();
if (filtered.isNotEmpty) {
notificationNoteInput = filtered.first;
}
filtered = getNotificationRespondAttributes.where((element) => element.attributeName == "FORWARD_TO_USERNAME_RESPONSE").toList();
if (filtered.isNotEmpty) {
forwardToUser = filtered.first;
}
showDialog(
context: context,
builder: (cxt) => AcceptRejectInputDialog(
message: title != null ? null : LocaleKeys.requestedItems.tr(),
// title: title,
notificationGetRespond: notificationNoteInput,
actionMode: apiMode,
onTap: (note) {
performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: [
if ((apiMode == "FORWARD" || apiMode == "APPROVE_AND_FORWARD") && forwardToUser != null)
{"ATTRIBUTE_NAME": "FORWARD_TO_USERNAME_RESPONSE", "ATTRIBUTE_TEXT_VALUE": actionHistoryList?.uSERNAME},
if (notificationNoteInput != null)
{
"ATTRIBUTE_NAME": notificationNoteInput.attributeName,
if (notificationNoteInput.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note
}
]);
},
),
);
}
void getUserInformation(BuildContext context) async {
String? empID = "";
if (actionHistoryList != null) empID = actionHistoryList!.uSERNAME;
@ -137,10 +182,17 @@ class SelectedItemSheet extends StatelessWidget {
}
}
Future<void> performNetworkCall(BuildContext context, {String? email, String? userId}) async {
Future<void> performNetworkCall(BuildContext context, {String? email, String? userId, List<Map<String, dynamic>>? attributeData = const []}) async {
Utils.showLoading(context);
try {
await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode, approverIndex: actionHistoryList != null ? actionHistoryList!.sEQUENCE : null);
await WorkListApiClient().submitComment(
comment: comment,
email: email,
userId: userId,
notificationId: notificationID,
apiMode: apiMode,
approverIndex: actionHistoryList != null ? actionHistoryList!.sEQUENCE : null,
attributeData: attributeData);
Utils.hideLoading(context);
// Navigator.pop(context);
// Navigator.pop(context);

@ -93,10 +93,12 @@ class _WorkListScreenState extends State<WorkListScreen> {
final ScrollController _controller = ScrollController();
int pNotificationType = 1;
ScrollController? _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController()..addListener(_scrollListener);
providerData = Provider.of<DashboardProviderModel>(context, listen: false);
calculateCounter();
if (workListItemIndex != null) getWorkList();
@ -154,7 +156,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
ItgFormsModel? itgFormsModel;
int? itgRequestTypeIndex;
Future<void> getWorkList({bool showLoading = true}) async {
Future<void> getWorkList({bool showLoading = true, bool isCallingFromRefresh = false}) async {
try {
if (showLoading) Utils.showLoading(context);
if (workListItemTypes[workListItemIndex!].key == "ITG") {
@ -173,7 +175,12 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
} else {
itgRequestTypeIndex = null;
workList = await WorkListApiClient().getWorkList(pageNumber, workListItemTypes[workListItemIndex!].key, pNotificationType.toString());
List<WorkListResponseModel>? _list = await WorkListApiClient().getWorkList(pageNumber, workListItemTypes[workListItemIndex!].key, pNotificationType.toString());
if (workList != null && _list != null && !isCallingFromRefresh) {
workList!.addAll(_list);
} else {
workList = _list;
}
AppState().setWorkList = workList;
}
if (showLoading) Utils.hideLoading(context);
@ -188,9 +195,10 @@ class _WorkListScreenState extends State<WorkListScreen> {
try {
_refreshController.refreshCompleted();
Utils.showLoading(context);
pageNumber = 1;
List dataOnRefresh = await Future.wait([
providerData.fetchWorkListCounter(context, showLoading: false),
getWorkList(showLoading: false),
getWorkList(showLoading: false, isCallingFromRefresh: true),
]);
calculateCounter();
Utils.hideLoading(context);
@ -203,9 +211,19 @@ class _WorkListScreenState extends State<WorkListScreen> {
@override
void dispose() {
_scrollController?.dispose();
super.dispose();
}
void _scrollListener() {
if (_scrollController!.position.pixels == _scrollController!.position.maxScrollExtent) {
pageNumber = pageNumber + 1;
if (itgRequestTypeIndex == null && workListItemTypes[workListItemIndex!].value != workList!.length) {
getWorkList();
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -236,6 +254,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
if (workListItemIndex != index && !workListItemTypes[index].disable) {
workListItemIndex = index;
pageNumber = 1;
if (workListItemTypes[index].value == 0) {
workList = [];
itgRequestTypeIndex = null;
@ -273,6 +292,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
),
controller: _refreshController,
onRefresh: _onRefresh,
scrollController: _scrollController,
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: itgRequestTypeIndex != null
@ -354,7 +374,6 @@ class _WorkListScreenState extends State<WorkListScreen> {
setState(() {});
}
}
} else {
verifyWorkListCounter();
if (mounted) setState(() {});

@ -449,7 +449,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
}
void handleFabAction(GetNotificationButtonsList notificationButton) {
print("notificationButton:${notificationButton.bUTTONACTION}");
switch (notificationButton.bUTTONACTION) {
case "DELEGATE":
showMyBottomSheet(context,
@ -526,6 +525,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
notificationID: workListData!.nOTIFICATIONID,
actionHistoryList: actionHistoryList,
callBackFunc: reloadWorkList,
getNotificationRespondAttributes: getNotificationRespondAttributes,
));
break;
case "FORWARD":
@ -537,8 +537,12 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
notificationID: workListData!.nOTIFICATIONID,
actionHistoryList: actionHistoryList,
callBackFunc: reloadWorkList,
getNotificationRespondAttributes: getNotificationRespondAttributes,
));
break;
case "DEL":
performAction(notificationButton.bUTTONACTION!);
break;
case "REJECT":
performAction(notificationButton.bUTTONACTION!);
break;
@ -565,6 +569,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
actionHistoryList: actionHistoryList.last,
notificationID: workListData!.nOTIFICATIONID,
isITGRequest: false,
getNotificationRespondAttributes: getNotificationRespondAttributes,
));
setState(() {});
} catch (ex) {
@ -656,7 +661,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
}
void performAction(String actionMode, {String? title}) {
print(actionMode);
showDialog(
context: context,
builder: (cxt) => AcceptRejectInputDialog(
@ -1003,19 +1007,11 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try {
isActionHistoryLoaded = false;
actionHistoryList.clear();
// if (apiCallCount == 0) Utils.showLoading(context);
// apiCallCount++;
actionHistoryList = await WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!);
// apiCallCount--;
// if (apiCallCount == 0) {
// Utils.hideLoading(context);
setState(() {
isActionHistoryLoaded = true;
});
// }
} catch (ex) {
// apiCallCount--;
// Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
@ -1024,88 +1020,15 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try {
isAttachmentLoaded = false;
getAttachmentList.clear();
// if (apiCallCount == 0) Utils.showLoading(context);
// apiCallCount++;
getAttachmentList = await WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!);
// apiCallCount--;
// if (apiCallCount == 0) {
// Utils.hideLoading(context);
setState(() {
isAttachmentLoaded = true;
});
// }
} catch (ex) {
// apiCallCount--;
// Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
// Widget showUpdateContinueSheet(List<GetEitCollectionNotificationBodyList> list) {
// double itemHeight = 0;
// double itemWidth = 0;
// var size = MediaQuery.of(context).size;
// itemHeight = (size.height - kToolbarHeight - 24) / 9;
// itemWidth = size.width / 2;
// return Column(
// children: [
// if ((workListData?.sUBJECT ?? "").isNotEmpty) workListData!.sUBJECT!.toText14().paddingOnly(top: 10, right: 21, left: 21, bottom: 21),
// ListView.separated(
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// itemBuilder: (cxt, index) {
// List<CollectionNotificationEit> dataList = list.isEmpty ? [] : (list[index].collectionNotification ?? []);
// dataList = dataList.where((o) => o.displayFlag == "Y").toList();
// bool isOdd = false;
// if (dataList.length % 2 != 0) {
// isOdd = true;
// dataList.add(new CollectionNotificationEit());
// }
// return GridView.builder(
// itemCount: dataList.length,
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// itemBuilder: (context, index) => ItemDetailViewGridItem(
// index,
// dataList[index].segmentPrompt,
// dataList[index].segmentValueDsp,
// isNeedToShowEmptyDivider: (dataList.length == index + 1)
// ? isOdd
// ? true
// : false
// : false,
// ),
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2,
// childAspectRatio: (itemWidth / itemHeight),
// ),
// ).objectContainerView();
// },
// separatorBuilder: (cxt, index) => 12.height,
// itemCount: list.length,
// ),
// Padding(
// padding: const EdgeInsets.only(right: 21, left: 21, bottom: 21),
// child: Row(
// children: [
// DefaultButton(
// LocaleKeys.edit.tr(),
// () => performEditAction(),
// colors: const [Color(0xffE47A7E), Color(0xffDE6D71)],
// ).expanded,
// 8.width,
// DefaultButton(
// LocaleKeys.next.tr(),
// () => performNextAction(),
// colors: const [Color(0xff28C884), Color(0xff1BB271)],
// ).expanded,
// ],
// ),
// ),
// ],
// );
// }
Widget showLoadingAnimation() {
return Lottie.asset(
'assets/lottie/loading.json',

@ -1,7 +1,9 @@
import 'package:easy_localization/src/public_ext.dart';
import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
@ -10,7 +12,8 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_item_creation_ntf_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_mo_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart' as get_pr_notification_body_list_model;
import 'package:mohem_flutter_app/ui/work_list/item_history_screen.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart';
@ -19,14 +22,14 @@ class RequestFragment extends StatelessWidget {
final List<GetMoNotificationBodyList> moNotificationBodyList;
final List<ItemCreationLines> itemCreationLines;
final List<POLines> poLinesList;
final List<PRLines> prLinesList;
final List<get_pr_notification_body_list_model.PRLines> prLinesList;
RequestFragment({
Key? key,
this.moNotificationBodyList = const <GetMoNotificationBodyList>[],
this.itemCreationLines = const <ItemCreationLines>[],
this.poLinesList = const <POLines>[],
this.prLinesList = const <PRLines>[],
this.prLinesList = const <get_pr_notification_body_list_model.PRLines>[],
}) : super(key: key);
@override
@ -37,7 +40,7 @@ class RequestFragment extends StatelessWidget {
padding: const EdgeInsets.all(21),
children: [
if (moNotificationBodyList.isNotEmpty) moNotificationDataView(),
if (poLinesList.isNotEmpty) poLinesDataView(),
if (poLinesList.isNotEmpty) poLinesDataView(context),
if (itemCreationLines.isNotEmpty) itemCreationLinesView(),
if (prLinesList.isNotEmpty) prLinesDataView(),
],
@ -45,7 +48,7 @@ class RequestFragment extends StatelessWidget {
);
}
Widget poLinesDataView() {
Widget poLinesDataView(BuildContext context) {
return ExpandableNotifier(
child: ListView.separated(
shrinkWrap: true,
@ -87,22 +90,38 @@ class RequestFragment extends StatelessWidget {
12.height,
Row(
children: [
DefaultButton(LocaleKeys.itemHistory.tr(), () {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(title: LocaleKeys.itemHistory.tr(), isMO: false, pItemId: poLinesList[index].iTEMID),
);
}).expanded,
DefaultButton(
LocaleKeys.itemHistory.tr(),
() {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(title: LocaleKeys.itemHistory.tr(), isMO: false, pItemId: poLinesList[index].iTEMID),
);
},
fontSize: 13,
).expanded,
12.width,
DefaultButton(LocaleKeys.quotationAnalysis.tr(), () {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, title: LocaleKeys.quotationAnalysis.tr(), pItemId: poLinesList[index].iTEMID, pPoHeaderId: poLinesList[index].pOHEADERID),
);
}).expanded,
DefaultButton(
LocaleKeys.quotationAnalysis.tr(),
() {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, title: LocaleKeys.quotationAnalysis.tr(), pItemId: poLinesList[index].iTEMID, pPoHeaderId: poLinesList[index].pOHEADERID),
);
},
fontSize: 13,
).expanded,
12.width,
DefaultButton(
"PR Details",
() {
getPRDetails(context, poLinesList[index].pOLINEID.toString());
},
fontSize: 13,
).expanded,
],
)
],
@ -263,4 +282,23 @@ class RequestFragment extends StatelessWidget {
separatorBuilder: (cxt, index) => 12.height,
itemCount: itemCreationLines.length);
}
void getPRDetails(BuildContext context, String poLineID) async {
try {
Utils.showLoading(context);
GetPRInformationList? getPRInformationList = GetPRInformationList();
getPRInformationList = await WorkListApiClient().getPRDetailsForPO(poLineID);
Utils.hideLoading(context);
Navigator.pushNamed(
context,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, isPRInfo: true, getPRInformationList: getPRInformationList, title: "PR Details", pItemId: 0, pPoHeaderId: 0),
);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}

@ -1,18 +1,20 @@
/* ZiK */
import 'dart:async';
import 'package:flutter/cupertino.dart';
typedef ChildProvider<E> = Widget Function(BuildContext context, E? data);
class Updater<T> extends StatelessWidget{
class Updater<T> extends StatelessWidget {
final ChildProvider<T> childProvider;
StreamController<T?>? sink;
T? initialData;
List<T?> _history = [];
Stream<T?>? _stream;
Updater({T? initialData, required this.childProvider}){
Updater({T? initialData, required this.childProvider}) {
this.sink = StreamController<T?>();
this.initialData = initialData;
_stream = this.sink?.stream;
@ -23,17 +25,17 @@ class Updater<T> extends StatelessWidget{
return StreamBuilder<T?>(
initialData: this.initialData,
stream: _stream,
builder: (ctx, snapshot){
return childProvider(context, snapshot.data);
});
builder: (ctx, snapshot) {
return childProvider(context, snapshot.data);
});
}
void pushData(T? data) {
_history.add(data);
sink?.sink.add(data);
}
List<T?> getDataHistory() => _history;
T? getLatestData() => _history.last;
}
T? getLatestData() => _history.last;
}

@ -1,13 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:provider/provider.dart';
AppBar AppBarWidget(BuildContext context,
{required String title,

@ -63,7 +63,7 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
void changeAccrualDate(bool showLoading) async {
try {
if (showLoading) Utils.showLoading(context);
List<GetAccrualBalancesList> accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: widget.selectedEmp);
List<GetAccrualBalancesList> accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy", "en_US").format(accrualDateTime), empID: widget.selectedEmp);
if (accrualList.isNotEmpty) {
if (widget.isLeaveBalance) {
leaveBalanceAccrual = accrualList[0];

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -26,7 +24,6 @@ import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class SearchEmployeeBottomSheet extends StatefulWidget {
int? notificationID;
@ -243,11 +240,11 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
children: [
Stack(
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
@ -307,13 +304,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
).onPress(
() {
if (provider.chatUsersList![index].isFav == null || provider.chatUsersList![index].isFav == false) {
provider
.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: provider.chatUsersList![index].id!,
fromSearch: true
)
.then((value) {
provider.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: provider.chatUsersList![index].id!, fromSearch: true).then((value) {
setState(() {});
});
} else if (provider.chatUsersList![index].isFav == true) {
@ -326,13 +317,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
setState(() {});
});
} else {
provider
.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: provider.chatUsersList![index].id!,
fromSearch: true
)
.then((value) {
provider.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: provider.chatUsersList![index].id!, fromSearch: true).then((value) {
setState(() {});
});
}

@ -5,8 +5,7 @@ import 'package:mohem_flutter_app/classes/colors.dart';
extension WithContainer on Widget {
Widget get insideContainer => Container(
color: Colors.white,
padding:
const EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21),
padding: const EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21),
child: this,
);
}
@ -76,8 +75,7 @@ class DefaultButton extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (iconData != null) Icon(iconData, color: textColor),
if (svgIcon != null)
SvgPicture.asset(svgIcon ?? "", color: textColor),
if (svgIcon != null) SvgPicture.asset(svgIcon ?? "", color: textColor),
if (!isTextExpanded)
Padding(
padding: EdgeInsets.only(

@ -0,0 +1,50 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/provider/hmg_connection_provider.dart';
import 'package:provider/provider.dart';
class HmgConnectivityButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
Provider.of<HmgConnectionProvider>(context, listen: false).checkHmgNetworkConnectivity();
return Consumer<HmgConnectionProvider>(
builder: (_, HmgConnectionProvider foo, __) {
return Container(
height: 45,
padding: const EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(200.0),
gradient: const LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: <Color>[
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
),
),
child: InkWell(
onTap: (){
},
child: Row(
children: [
const Icon(
Icons.wifi,
color: Colors.white,
),
12.width,
LocaleKeys.connectHmgWifi.tr().toText18(color: Colors.white),
],
),
),
);
},
);
}
}

@ -7,7 +7,6 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:provider/provider.dart';
AppBar ChatAppBarWidget(BuildContext context,

@ -12,8 +12,9 @@ class ConfirmDialog extends StatelessWidget {
final String message;
final String? okTitle;
final VoidCallback? onTap;
final VoidCallback? onCloseTap;
const ConfirmDialog({Key? key, this.title, required this.message, this.okTitle, this.onTap}) : super(key: key);
const ConfirmDialog({Key? key, this.title, required this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -41,9 +42,8 @@ class ConfirmDialog extends StatelessWidget {
icon: const Icon(Icons.close),
color: MyColors.darkTextColor,
constraints: const BoxConstraints(),
onPressed: () {
Navigator.pop(context);
},
onPressed: () => onCloseTap ?? Navigator.pop(context),
// onPressed: () => Navigator.pop(context),
)
],
),

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
void showMDialog(context, {Widget? child,Color? backgroundColor,bool isDismissable=true}) async {
void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true}) async {
return showDialog(
context: context,
barrierDismissible: isDismissable,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save