diff --git a/android/app/build.gradle b/android/app/build.gradle index e66b465..5279c1f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -71,10 +71,10 @@ android { signingConfig signingConfigs.debug } release { - signingConfig signingConfigs.debug - minifyEnabled false - shrinkResources false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } @@ -85,6 +85,4 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.squareup.okhttp3:okhttp:4.9.1' - } diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro deleted file mode 100644 index 419bd27..0000000 --- a/android/app/proguard-rules.pro +++ /dev/null @@ -1,27 +0,0 @@ --ignorewarnings --keepattributes *Annotation* --keepattributes Exceptions --keepattributes InnerClasses --keepattributes Signature --keepattributes SourceFile,LineNumberTable --keep class com.huawei.hianalytics.**{*;} --keep class com.huawei.updatesdk.**{*;} --keep class com.huawei.hms.**{*;} --keep class com.huawei.hms.flutter.**{*;} --keep class com.hiennv.flutter_callkit_incoming.** { *; } --keep class microsoft.aspnet.signalr.client.hubs.** { *; } --keep class com.microsoft.signalr.** { *; } --keep class tvi.webrtc.** { *; } --keep interface com.microsoft.signalr.** { *; } - - --repackageclasses - -## Flutter wrapper --keep class io.flutter.app.** { *; } --keep class io.flutter.plugin.** { *; } --keep class io.flutter.util.** { *; } --keep class io.flutter.view.** { *; } --keep class io.flutter.** { *; } --keep class io.flutter.plugins.** { *; } --dontwarn io.flutter.embedding.** \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 546a7f9..d092ef9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -35,7 +35,6 @@ android:icon="@mipmap/ic_launcher" android:label="Mohemm" android:extractNativeLibs="true" - android:usesCleartextTraffic="true" android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round"> postJsonForResponse(String url, T jsonObject, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { String? requestBody; + print(url); + print(jsonObject); late Map stringObj; if (jsonObject != null) { requestBody = jsonEncode(jsonObject); @@ -124,6 +126,7 @@ class ApiClient { if (isFormData) { headers = {'Content-Type': 'application/x-www-form-urlencoded'}; stringObj = ((jsonObject ?? {}) as Map).map((key, value) => MapEntry(key, value?.toString() ?? "")); + print(stringObj); } return await _postForResponse(url, isFormData ? stringObj : requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 7d6489a..6d325bd 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -34,7 +34,6 @@ class ChatApiClient { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "isMobile": true, - "platform": Platform.isIOS ? "ios" : "android", "deviceToken": AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken, "isHuaweiDevice": AppState().getIsHuawei, "platform": Platform.isIOS ? "ios" : "android", // ios, android @@ -142,14 +141,14 @@ class ChatApiClient { } // Upload Chat Media - Future uploadMedia(String userId, File file) async { + Future uploadMedia(String userId, File file, String fileSource) async { if (kDebugMode) { print("${ApiConsts.chatMediaImageUploadUrl}upload"); print(AppState().chatDetails!.response!.token); } dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatMediaImageUploadUrl}upload')); - request.fields.addAll({'userId': userId, 'fileSource': '1'}); + request.fields.addAll({'userId': userId, 'fileSource': fileSource}); request.files.add(await MultipartFile.fromPath('files', file.path)); request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); StreamedResponse response = await request.send(); @@ -161,10 +160,10 @@ class ChatApiClient { } // Download File For Chat - Future downloadURL({required String fileName, required String fileTypeDescription}) async { + Future downloadURL({required String fileName, required String fileTypeDescription, required int fileSource}) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatMediaImageUploadUrl}download", - {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": 1}, + {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": fileSource}, token: AppState().chatDetails!.response!.token, ); Uint8List data = Uint8List.fromList(response.bodyBytes); diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 847d282..6b4219f 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -194,6 +194,7 @@ class AppState { bool cancelRequestTrancsection = true; + String _iosVoipPlayerID = ""; String get iosVoipPlayerID => _iosVoipPlayerID; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 04b050d..a571e3b 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,8 +1,8 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver - // static String baseUrl = "https://hmgwebservices.com"; // Live server + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; @@ -18,13 +18,13 @@ class ApiConsts { static String chatLoginTokenUrl = chatServerBaseApiUrl + "user/"; static String chatHubConnectionUrl = chatServerBaseUrl + "ConnectionChatHub"; - //Groups - static String getGroupByUserId = chatServerBaseApiUrl + "group/getgroupsbyuserid/"; - static String deleteGroup = chatServerBaseApiUrl + "group/updateGroupIsDeleted/"; - static String updateGroupAdmin = chatServerBaseApiUrl + "group/updateGroupAdmin/"; - static String getGroupChatHistoryAsync = chatServerBaseApiUrl + "GroupChat/GetGroupChatHistoryAsync/"; - static String addGroupsAndUsers = chatServerBaseApiUrl + "group/addgroupandusers/"; - static String updateGroupsAndUsers = chatServerBaseApiUrl + "group/updategroupandusers/"; + //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 @@ -36,11 +36,7 @@ class ApiConsts { static String oneSignalAppID = "472e4582-5c44-47ab-a5f5-9369b8967107"; //Brain Marathon Constants - static String marathonBaseUrlLive = "https://marathoon.com/service/api/"; - static String marathonBaseUrlUAT = "https://marathoon.com/uatservice/api/"; - - static String marathonBaseUrl = marathonBaseUrlLive; - // static String marathonBaseUrl = marathonBaseUrlUAT; + static String marathonBaseUrl = "https://marathoon.com/service/api/"; static String marathonBaseUrlServices = "https://marathoon.com/service/"; static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get"; @@ -53,6 +49,7 @@ class ApiConsts { static String marathonGetMarathonersCount = marathonBaseUrl + "Participant/GetRemainingParticipants"; //DummyCards for the UI + static CardContent dummyQuestion = const CardContent(); static int tabletMinLength = 500; } diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 80f0d79..527c3aa 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -73,7 +73,7 @@ class AppNotifications { if (initialMessage != null) _handleMessage(initialMessage); FirebaseMessaging.onMessage.listen((RemoteMessage message) { - if (message.notification != null) _handleMessage(message); + _handleMessage(message); }); FirebaseMessaging.onMessageOpenedApp.listen(_handleOpenApp); @@ -134,23 +134,26 @@ class AppNotifications { Utils.saveStringFromPrefs("isAppOpendByChat", "false"); GetNotificationsResponseModel notification = GetNotificationsResponseModel(); - notification.createdOn = DateUtil.getMonthDayYearDateFormatted(DateTime.now()); - notification.messageTypeData = message.data['picture']; - notification.message = message.data['message']; - notification.notificationType = message.data["NotificationType"].toString(); - if (message.data["NotificationType"] == "2") { - notification.videoURL = message.data["VideoUrl"]; - } + if (message.notification != null) { + notification.createdOn = DateUtil.getMonthDayYearDateFormatted(DateTime.now()); + notification.messageTypeData = message.data['picture']; + notification.message = message.data['message']; + notification.notificationType = message.data["NotificationType"].toString(); + if (message.data["NotificationType"] == "2") { + notification.videoURL = message.data["VideoUrl"]; + } - Future.delayed(Duration(seconds: 5), () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (BuildContext context) => NotificationsDetailsPage( - notification: notification, + Future.delayed(Duration(seconds: 5), () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => NotificationsDetailsPage( + notification: notification, + ), ), - ), - ); - }); + ); + }); + } + if (message.data.isNotEmpty && message.data["messageType"] == 'chat') { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); @@ -187,8 +190,6 @@ class AppNotifications { }); } } - - } const AndroidNotificationChannel channel = AndroidNotificationChannel( diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index 4af7a8d..4105def 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -10,16 +10,16 @@ import 'package:audio_session/audio_session_web.dart'; import 'package:file_picker/_internal/file_picker_web.dart'; import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_messaging_web/firebase_messaging_web.dart'; -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:fluttertoast/fluttertoast_web.dart'; import 'package:geolocator_web/geolocator_web.dart'; import 'package:image_picker_for_web/image_picker_for_web.dart'; import 'package:just_audio_web/just_audio_web.dart'; -// import 'package:record_web/record_web.dart'; import 'package:shared_preferences_web/shared_preferences_web.dart'; import 'package:url_launcher_web/url_launcher_web.dart'; import 'package:video_player_web/video_player_web.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + // ignore: public_member_api_docs void registerPlugins(Registrar registrar) { AudioSessionWeb.registerWith(registrar); @@ -30,7 +30,6 @@ void registerPlugins(Registrar registrar) { GeolocatorPlugin.registerWith(registrar); ImagePickerPlugin.registerWith(registrar); JustAudioPlugin.registerWith(registrar); - //RecordPluginWeb.registerWith(registrar); SharedPreferencesPlugin.registerWith(registrar); UrlLauncherPlugin.registerWith(registrar); VideoPlayerPlugin.registerWith(registrar); diff --git a/lib/main.dart b/lib/main.dart index ad269d5..3033349 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,6 +20,7 @@ import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:sizer/sizer.dart'; +late HubConnection chatHubConnection; // test uat account // username 199067 diff --git a/lib/models/chat/create_group_request.dart b/lib/models/chat/create_group_request.dart index b33297f..1f5bfd2 100644 --- a/lib/models/chat/create_group_request.dart +++ b/lib/models/chat/create_group_request.dart @@ -4,6 +4,8 @@ class CreateGroupRequest { String? groupName; int? adminUserId; List? groupUserList; + List? addedUsers; + List? removedUsers; bool? canAttach; bool? canAudioC; bool? canShareS; @@ -15,6 +17,8 @@ class CreateGroupRequest { {this.groupName, this.adminUserId, this.groupUserList, + this.addedUsers, + this.removedUsers, this.canAttach, this.canAudioC, this.canShareS, @@ -27,12 +31,24 @@ class CreateGroupRequest { CreateGroupRequest.fromJson(Map json) { groupName = json['groupName']; adminUserId = json['adminUserId']; + if (json['removedUsers'] != null) { + groupUserList = []; + json['removedUsers'].forEach((v) { + groupUserList!.add(new ChatUser.fromJson(v)); + }); + } if (json['groupUserList'] != null) { groupUserList = []; json['groupUserList'].forEach((v) { groupUserList!.add(new ChatUser.fromJson(v)); }); } + if (json['addedUsers'] != null) { + groupUserList = []; + json['addedUsers'].forEach((v) { + groupUserList!.add(new ChatUser.fromJson(v)); + }); + } canAttach = json['canAttach']; canAudioC = json['canAudioC']; canShareS = json['canShareS']; @@ -50,6 +66,14 @@ class CreateGroupRequest { data['groupUserList'] = this.groupUserList!.map((v) => v.toJson()).toList(); } + if (this.addedUsers != null) { + data['addedUsers'] = + this.addedUsers!.map((v) => v.toJson()).toList(); + } + if (this.removedUsers != null) { + data['removedUsers'] = + this.removedUsers!.map((v) => v.toJson()).toList(); + } data['canAttach'] = this.canAttach; data['canAudioC'] = this.canAudioC; data['canShareS'] = this.canShareS; diff --git a/lib/models/chat/get_user_groups_by_id.dart b/lib/models/chat/get_user_groups_by_id.dart index 2520c43..e0219a5 100644 --- a/lib/models/chat/get_user_groups_by_id.dart +++ b/lib/models/chat/get_user_groups_by_id.dart @@ -1,7 +1,7 @@ import 'dart:convert'; class GetUserGroups { - List? groupresponse; + List? groupresponse =[]; Null? errorResponses; GetUserGroups({this.groupresponse, this.errorResponses}); diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index a43a55c..47576f3 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -86,15 +86,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { /// Search Provider List? chatUsersList = []; int pageNo = 1; - - bool disbaleChatForThisUser = false; List? uGroups = [], searchGroups = []; + bool disbaleChatForThisUser = false; bool disableChatForThisUser = false; bool isUserOnline = false; bool isCall = false; - userLoginToken.UserAutoLoginModel userLoginData = userLoginToken.UserAutoLoginModel(); - Future getUserAutoLoginToken() async { try { userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); @@ -111,7 +108,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Utils.showToast( userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", ); - disableChatForThisUser = true; + disableChatForThisUser = false; + + isUserOnline = false; if (Platform.isIOS) { AppState().setisUserOnline = false; @@ -140,11 +139,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion); - ccProvider.initCallListeners(context: context); //group On message chatHubConnection.on("OnDeliveredGroupChatHistoryAsync", onGroupMsgReceived); + ccProvider.initCallListeners(context: context); } Future getHubConnection() async { @@ -164,10 +163,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatHubConnection.on("OnUserTypingAsync", onUserTyping); chatHubConnection.on("OnUserCountAsync", userCountAsync); // chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); - chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); - chatHubConnection.on("OnGetGroupUserStatusAsync", getGroupUserStatus); - + chatHubConnection.on( + "OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + chatHubConnection.on( + "OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + chatHubConnection.on( + "OnGetGroupUserStatusAsync", getGroupUserStatus); + chatHubConnection.on( + "OnAddGroupChatHistoryAsync", groupChatHistoryAsync); // // {"type":1,"target":"","arguments":[[{"id":217869,"userName":"Sultan.Khan","email":"Sultan.Khan@cloudsolutions.com.sa","phone":null,"title":"Sultan.Khan","userStatus":1,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":false,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null},{"id":15153,"userName":"Tamer.Fanasheh","email":"Tamer.F@cloudsolutions.com.sa","phone":null,"title":"Tamer Fanasheh","userStatus":2,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":true,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null}]]} @@ -179,7 +182,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getUserRecentChats() async { ChatUserModel recentChat = await ChatApiClient().getRecentChats(); ChatUserModel favUList = await ChatApiClient().getFavUsers(); - // userGroups = await ChatApiClient().getGroupsByUserId(); + userGroups = await ChatApiClient().getGroupsByUserId(); if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); @@ -293,10 +296,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List getGroupChatHistoryAsync(String str) => List.from(json.decode(str).map((x) => groupchathistory.GetGroupChatHistoryAsync.fromJson(x))); - Future uploadAttachments(String userId, File file) async { + Future uploadAttachments(String userId, File file, String fileSource) async { dynamic result; try { - Object? response = await ChatApiClient().uploadMedia(userId, file); + Object? response = await ChatApiClient().uploadMedia(userId, file, fileSource); if (response != null) { result = response; } else { @@ -321,8 +324,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - void getGroupUserStatus(List? args) { - //note: need to implement this function... + void getGroupUserStatus(List? args){ + //note: need to implement this function when group user status + + print(args); + } + void groupChatHistoryAsync(List? args){ + //need to imlement this event when any group details updated. print(args); } @@ -421,15 +429,22 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserId = temp.first.targetUserId; data.first.currentUserName = temp.first.targetUserName; data.first.currentUserEmail = temp.first.targetUserEmail; - if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) { - data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); + data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg",fileSource: 1); } if (data.first.userChatReplyResponse != null) { if (data.first.fileTypeResponse != null) { - if (data.first.userChatReplyResponse!.fileTypeId == 12 || data.first.userChatReplyResponse!.fileTypeId == 4 || data.first.userChatReplyResponse!.fileTypeId == 3) { - data.first.userChatReplyResponse!.image = - await ChatApiClient().downloadURL(fileName: data.first.userChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); + if (data.first.userChatReplyResponse!.fileTypeId == 12 || + data.first.userChatReplyResponse!.fileTypeId == 4 || + data.first.userChatReplyResponse!.fileTypeId == 3) { + data.first.userChatReplyResponse!.image = await ChatApiClient() + .downloadURL( + fileName: data.first.userChatReplyResponse!.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg", + fileSource:1 + ); data.first.userChatReplyResponse!.isImageLoaded = true; } } @@ -501,14 +516,30 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // data.first.currentUserId = temp.first.currentUserId; // data.first.currentUserName = temp.first.currentUserName; - if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) { - data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); + + if (data.first.fileTypeId == 12 || + data.first.fileTypeId == 4 || + data.first.fileTypeId == 3) { + data.first.image = await ChatApiClient().downloadURL( + fileName: data.first.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg", + fileSource:2 + ); } if (data.first.groupChatReplyResponse != null) { if (data.first.fileTypeResponse != null) { - if (data.first.groupChatReplyResponse!.fileTypeId == 12 || data.first.groupChatReplyResponse!.fileTypeId == 4 || data.first.groupChatReplyResponse!.fileTypeId == 3) { - data.first.groupChatReplyResponse!.image = - await ChatApiClient().downloadURL(fileName: data.first.groupChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); + if (data.first.groupChatReplyResponse!.fileTypeId == 12 || + data.first.groupChatReplyResponse!.fileTypeId == 4 || + data.first.groupChatReplyResponse!.fileTypeId == 3) { + data.first.groupChatReplyResponse!.image = await ChatApiClient() + .downloadURL( + fileName: data.first.groupChatReplyResponse!.contant!, + fileTypeDescription: + data.first.fileTypeResponse!.fileTypeDescription ?? + "image/jpg", + fileSource:2); data.first.groupChatReplyResponse!.isImageLoaded = true; } } @@ -587,8 +618,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (isChatScreenActive && data.first.currentUserId == receiverID) { int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == 0); - - logger.d(index); userChatHistory[index] = data.first; } @@ -649,6 +678,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return 13; case ".mp3": return 14; + case ".mp4": + return 16; + case ".mov": + return 16; + case ".avi": + return 16; + case ".flv": + return 16; default: return 0; } @@ -686,6 +723,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return "audio/aac"; case ".mp3": return "audio/mp3"; + case ".mp4": + return "video/mp4"; + case ".avi": + return "video/avi"; + case ".flv": + return "video/flv"; + case ".mov": + return "video/mov"; default: return ""; } @@ -814,7 +859,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (kDebugMode) { logger.i("model data: " + jsonEncode(data)); } - groupChatHistory.insert(0, data); + // groupChatHistory.insert(0, data); isTextMsg = false; isReplyMsg = false; isAttachmentMsg = false; @@ -887,7 +932,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { logger.d("// Normal Image Message"); Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile,'2'); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendGroupChatToServer( @@ -907,7 +953,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) { logger.d("// Image as Reply Msg"); Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile,'2'); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendGroupChatToServer( @@ -943,8 +990,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isPlaying = false; isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile); - String? ext = getFileExtension(voiceFile.path); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile,'2'); + String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendGroupChatToServer( chatEventId: 2, @@ -979,8 +1027,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile); - String? ext = getFileExtension(voiceFile.path); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile,'2'); + String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendGroupChatToServer( chatEventId: 2, @@ -1081,7 +1130,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { logger.d("// Normal Image Message"); Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile,'1'); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1100,7 +1150,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) { logger.d("// Image as Reply Msg"); Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), selectedFile,'1'); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1135,7 +1186,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isPlaying = false; isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile, '1'); String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1169,7 +1221,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile); + dynamic value = await uploadAttachments( + AppState().chatDetails!.response!.id.toString(), voiceFile, '1'); String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1271,8 +1324,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool checkFileSize(String path) { int fileSizeLimit = 1024; File f = File(path); - double fileSizeInKB = f.lengthSync() / 1024; - double fileSizeInMB = fileSizeInKB / 1024; + double fileSizeInKB = f.lengthSync() / 5000; + double fileSizeInMB = fileSizeInKB / 5000; if (fileSizeInKB > fileSizeLimit) { return false; } else { @@ -1453,6 +1506,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { pChatHistory?.clear(); uGroups?.clear(); searchGroup?.clear(); + // callP.stopListeners(); chatHubConnection.stop(); AppState().chatDetails = null; } @@ -1564,10 +1618,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - Future getChatMedia(BuildContext context, {required String fileName, required String fileTypeName, required int fileTypeID}) async { + Future getChatMedia(BuildContext context, + {required String fileName, + required String fileTypeName, + required int fileTypeID, + required int fileSource}) async { Utils.showLoading(context); - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) { - Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName)); + if (fileTypeID == 1 || + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 || + fileTypeID == 2 || fileTypeID ==16) { + Uint8List encodedString = await ChatApiClient().downloadURL( + fileName: fileName, + fileTypeDescription: getFileTypeDescription(fileTypeName), + fileSource: fileSource + ); try { String path = await downChatMedia(encodedString, fileTypeName ?? ""); Utils.hideLoading(context); diff --git a/lib/ui/chat/call/chat_incoming_call_screen.dart b/lib/ui/chat/call/chat_incoming_call_screen.dart index 81645c3..8056292 100644 --- a/lib/ui/chat/call/chat_incoming_call_screen.dart +++ b/lib/ui/chat/call/chat_incoming_call_screen.dart @@ -154,7 +154,7 @@ class _StartCallPageState extends State { RTCVideoView( provider.remoteRenderer!, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, - filterQuality: FilterQuality.high, + // filterQuality: FilterQuality.high, key: const Key('remote'), ), if (provider.isVideoCall) @@ -174,7 +174,7 @@ class _StartCallPageState extends State { child: RTCVideoView( provider.localVideoRenderer!, mirror: true, - filterQuality: FilterQuality.high, + // filterQuality: FilterQuality.high, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), ), diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index d6483dc..95815c1 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -82,7 +82,7 @@ class ChatBubble extends StatelessWidget { } } else { Utils.showLoading(context); - Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? "")); + Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""), fileSource:1); // try { File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); if (sFile.path.isEmpty) { @@ -342,7 +342,7 @@ class ChatBubble extends StatelessWidget { ); } else { return FutureBuilder( - future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription), + future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource:1), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.waiting) { if (snapshot.data == null) { diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 9c585be..90f7bb2 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -175,7 +175,7 @@ class _ChatDetailScreenState extends State { // || m.userChatHistory[i].fileTypeId! == 2 ) { m.getChatMedia(context, - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!, fileSource:1); } } }); diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index a31cfb4..f16b344 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -68,7 +68,8 @@ class _ChatHomeState extends State { fetchAgain(); return Scaffold( backgroundColor: MyColors.white, - appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), + + appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true, isBackButton: false), body: Column( children: [ Container( @@ -91,7 +92,7 @@ class _ChatHomeState extends State { child: Row( children: [ myTab(LocaleKeys.mychats.tr(), 0), - // myTab(LocaleKeys.group.tr(), 1), + myTab(LocaleKeys.group.tr(), 1), myTab(LocaleKeys.favorite.tr(), 2), AppState().getempStatusIsManager ? myTab(LocaleKeys.myTeam.tr(), 3) : const SizedBox(), ], @@ -107,7 +108,7 @@ class _ChatHomeState extends State { }, children: [ ChatHomeScreen(), - // GropChatHomeScreen(), + GropChatHomeScreen(), ChatFavoriteUsersScreen(), AppState().getempStatusIsManager ? const MyTeamScreen() : const SizedBox(), ], diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 04d7c2e..a2c98d2 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -217,9 +217,10 @@ class _ChatHomeScreenState extends State { child: Container( width: 60, height: 60, - decoration: const BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + //shape: BoxShape.circle, + gradient:const LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, diff --git a/lib/ui/chat/create_group.dart b/lib/ui/chat/create_group.dart index 43b2635..17f5fc1 100644 --- a/lib/ui/chat/create_group.dart +++ b/lib/ui/chat/create_group.dart @@ -36,7 +36,6 @@ class CreateGroupBottomSheet extends StatefulWidget { Function(ReplacementList) onSelectEmployee; bool fromChat; groups.GroupResponse groupDetails; - CreateGroupBottomSheet({ Key? key, required this.title, @@ -77,7 +76,8 @@ class _CreateGroupBottomSheetState extends State { int _selectedSearchIndex = 0; List selectedUsers = []; - + List addedUser = []; + List removedUser = []; void fetchUserByInput({bool isNeedLoading = true}) async { try { Utils.showLoading(context); @@ -397,6 +397,8 @@ class _CreateGroupBottomSheetState extends State { if (user.isNotEmpty) { user.first.isChecked = false; } + selectedUsers[index2].userAction =2; + removedUser.add(selectedUsers[index2]); selectedUsers.remove( selectedUsers[index2]); }); @@ -535,8 +537,12 @@ class _CreateGroupBottomSheetState extends State { if (provider.chatUsersList![index] .isChecked == true) { + provider + .chatUsersList![index].userAction =1; selectedUsers.add(provider .chatUsersList![index]); + + } else { selectedUsers.remove(provider .chatUsersList![index]); @@ -677,7 +683,7 @@ class _CreateGroupBottomSheetState extends State { admin.totalCount = 0; mainUsers.add(admin); CreateGroupRequest request = CreateGroupRequest( - groupUserList: [...selectedUsers, ...mainUsers].toList(), + groupUserList: [...selectedUsers, ...mainUsers, ...removedUser].toList(), canArchive: false, isMeeting: false, canShareS: isShareScreen, diff --git a/lib/ui/chat/group_chat.dart b/lib/ui/chat/group_chat.dart index 35b4c5c..7c0ffde 100644 --- a/lib/ui/chat/group_chat.dart +++ b/lib/ui/chat/group_chat.dart @@ -199,9 +199,10 @@ class _GropChatHomeScreenState extends State { child: Container( width: 60, height: 60, - decoration: const BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + // shape: BoxShape.circle, + gradient:const LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, diff --git a/lib/ui/chat/group_chat_bubble.dart b/lib/ui/chat/group_chat_bubble.dart index 69a50df..7b3db77 100644 --- a/lib/ui/chat/group_chat_bubble.dart +++ b/lib/ui/chat/group_chat_bubble.dart @@ -22,6 +22,7 @@ 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'; +import 'package:video_player/video_player.dart'; class GroupChatBubble extends StatelessWidget { GroupChatBubble({Key? key, required this.dateTime, required this.cItem}) @@ -100,7 +101,7 @@ class GroupChatBubble extends StatelessWidget { Uint8List encodedString = await ChatApiClient().downloadURL( fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription( - data.fileTypeResponse!.fileTypeName ?? "")); + data.fileTypeResponse!.fileTypeName ?? ""), fileSource: 2); // try { File sFile = await provider.downChatVoice( encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); @@ -245,8 +246,11 @@ class GroupChatBubble extends StatelessWidget { child: showImage( isReplyPreview: false, fileName: cItem.contant!, - fileTypeDescription: - cItem.fileTypeResponse!.fileTypeDescription) + fileTypeDescription: cItem.fileTypeResponse != null && + cItem.fileTypeResponse!.fileTypeDescription != + null + ? cItem.fileTypeResponse!.fileTypeDescription + : cItem.fileTypeResponse!.fileTypeName) .onPress(() { showDialog( context: context, @@ -258,17 +262,19 @@ class GroupChatBubble extends StatelessWidget { ), ).paddingOnly(bottom: 4), if (fileTypeID == 13 && cItem.voiceController != null) - currentWaveBubble(context, cItem) + currentWaveBubble(context, cItem), + if (fileTypeID == 16) + showVideoThumb(context, cItem) else Row( children: [ if (fileTypeID == 1 || - fileTypeID == 5 || - fileTypeID == 7 || - fileTypeID == 6 || - fileTypeID == 8 - // || fileTypeID == 2 - ) + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + // || fileTypeID == 2 + ) SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, @@ -279,12 +285,12 @@ class GroupChatBubble extends StatelessWidget { textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded), if (fileTypeID == 1 || - fileTypeID == 5 || - fileTypeID == 7 || - fileTypeID == 6 || - fileTypeID == 8 - //|| fileTypeID == 2 - ) + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + //|| fileTypeID == 2 + ) const Icon(Icons.remove_red_eye, size: 16) ], ), @@ -422,23 +428,27 @@ class GroupChatBubble extends StatelessWidget { ), ).paddingOnly(bottom: 4), if (fileTypeID == 13 && cItem.voiceController != null) - recipetWaveBubble(context, cItem) + recipetWaveBubble(context, cItem), + if (fileTypeID == 16) + showVideoThumb(context, cItem) else Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - cItem.currentUserName!.toText10( - color: Colors.black, - ).paddingOnly(bottom: 5), + cItem.currentUserName! + .toText10( + color: Colors.black, + ) + .paddingOnly(bottom: 5), Row( children: [ if (fileTypeID == 1 || - fileTypeID == 5 || - fileTypeID == 7 || - fileTypeID == 6 || - fileTypeID == 8 - // || fileTypeID == 2 - ) + fileTypeID == 5 || + fileTypeID == 7 || + fileTypeID == 6 || + fileTypeID == 8 + // || fileTypeID == 2 + ) SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, @@ -452,21 +462,23 @@ class GroupChatBubble extends StatelessWidget { .toText12(color: Colors.white) .expanded), if (fileTypeID == 1 || - fileTypeID == 5 || - fileTypeID == 7 || - fileTypeID == 6 || - fileTypeID == 8 - //|| fileTypeID == 2 - ) + 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), + child: dateTime + .toText10( + color: Colors.white.withOpacity(.71), + ) + .paddingOnly(top: 5), ), ], ), @@ -492,7 +504,7 @@ class GroupChatBubble extends StatelessWidget { } else { return FutureBuilder( future: ChatApiClient().downloadURL( - fileName: fileName, fileTypeDescription: fileTypeDescription), + fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource:2), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.waiting) { if (snapshot.data == null) { @@ -557,6 +569,11 @@ class GroupChatBubble extends StatelessWidget { ).circle(5); } + Widget showVideoThumb(BuildContext context, GetGroupChatHistoryAsync data) { + + return LoadVideo(data: data); + } + Widget recipetWaveBubble( BuildContext context, GetGroupChatHistoryAsync data) { return Container( @@ -641,3 +658,51 @@ class GroupChatBubble extends StatelessWidget { ); } } + +class LoadVideo extends StatefulWidget { + final GetGroupChatHistoryAsync data; + const LoadVideo({Key? key, required this.data}) : super(key: key); + + @override + State createState() => _LoadVideoState(); +} + +class _LoadVideoState extends State { + late VideoPlayerController videoController; + + @override + void initState() { + videoController = VideoPlayerController.networkUrl(Uri.parse( + 'https://apiderichat.hmg.com/groupattachments/${widget.data.fileTypeResponse?.fileName}')) + ..initialize().then((_) { + + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: AspectRatio( + aspectRatio: videoController.value.aspectRatio, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(videoController), + Align( + alignment: Alignment.center, + child: Icon( + Icons.play_arrow, + color: Colors.white.withOpacity(.7), + size: 56, + ), + ) + ], + ), + )); + } +} diff --git a/lib/ui/chat/group_chat_detaied_screen.dart b/lib/ui/chat/group_chat_detaied_screen.dart index 3a828f9..130ccb3 100644 --- a/lib/ui/chat/group_chat_detaied_screen.dart +++ b/lib/ui/chat/group_chat_detaied_screen.dart @@ -113,217 +113,221 @@ class _GroupChatDetailScreenState extends State { isDetailedScreen: true, ) : Column( - children: [ - SmartRefresher( - enablePullDown: false, - enablePullUp: true, - onLoading: () { - getMoreChat(); - }, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, + children: [ + SmartRefresher( + enablePullDown: false, + enablePullUp: true, + onLoading: () { + getMoreChat(); + }, + header: const MaterialClassicHeader( + color: MyColors.gradiantEndColor, + ), + controller: _rc, + reverse: true, + child: ListView.separated( + controller: m.scrollController, + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + reverse: true, + itemCount: m.groupChatHistory.length, + padding: const EdgeInsets.all(21), + separatorBuilder: (BuildContext cxt, int index) => 8.height, + itemBuilder: (BuildContext context, int i) { + return SwipeTo( + iconColor: MyColors.lightGreenColor, + child: GroupChatBubble( + dateTime: m.groupChatHistory[i].createdDate!, + cItem: m.groupChatHistory[i], ), - controller: _rc, - reverse: true, - child: ListView.separated( - controller: m.scrollController, - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - reverse: true, - itemCount: m.groupChatHistory.length, - padding: const EdgeInsets.all(21), - separatorBuilder: (BuildContext cxt, int index) => 8.height, - itemBuilder: (BuildContext context, int i) { - return SwipeTo( - iconColor: MyColors.lightGreenColor, - child: GroupChatBubble( - dateTime: m.groupChatHistory[i].createdDate!, - cItem: m.groupChatHistory[i], - ), - onRightSwipe: (val) { - m.groupChatReply( - m.groupChatHistory[i], - ); - }, - ).onPress(() async { - logger.w(m.userChatHistory[i].toJson()); - if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) { - if (m.userChatHistory[i].fileTypeId! == 1 || - m.userChatHistory[i].fileTypeId! == 5 || - m.userChatHistory[i].fileTypeId! == 7 || - m.userChatHistory[i].fileTypeId! == 6 || - m.userChatHistory[i].fileTypeId! == 8 - // || m.userChatHistory[i].fileTypeId! == 2 - ) { - m.getChatMedia(context, - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); - } - } - }); - }, - ), - ).expanded, - if (m.isReplyMsg) - SizedBox( - height: 82, + onRightSwipe: (val) { + m.groupChatReply( + m.groupChatHistory[i], + ); + }, + ).onPress(() async { + logger.w(m.groupChatHistory[i].toJson()); + if (m.groupChatHistory[i].fileTypeResponse != null && m.groupChatHistory[i].fileTypeId != null) { + if (m.groupChatHistory[i].fileTypeId! == 1 || + m.groupChatHistory[i].fileTypeId! == 5 || + m.groupChatHistory[i].fileTypeId! == 7 || + m.groupChatHistory[i].fileTypeId! == 6 || + m.groupChatHistory[i].fileTypeId! == 8 + || m.groupChatHistory[i].fileTypeId! == 16 + ) { + m.getChatMedia(context, + fileTypeName: m.groupChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.groupChatHistory[i].fileTypeId!, fileName: m.groupChatHistory[i].contant!,fileSource: 2); + } + } + }); + }, + ), + ).expanded, + if (m.isReplyMsg) + SizedBox( + height: 82, + child: Row( + children: [ + Container(height: 82, color: MyColors.textMixColor, width: 6), + Container( + color: MyColors.darkTextColor.withOpacity(0.10), + padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), child: Row( - children: [ - Container(height: 82, color: MyColors.textMixColor, width: 6), - Container( - color: MyColors.darkTextColor.withOpacity(0.10), - padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (AppState().chatDetails!.response!.userName == m.groupChatReplyData.first.currentUserName.toString() - ? "You" - : m.groupChatReplyData.first.currentUserName.toString().replaceAll(".", " ")) - .toText14(color: MyColors.lightGreenColor), - (m.groupChatReplyData.isNotEmpty ? m.groupChatReplyData.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) - ], - ).expanded, - 12.width, - if (m.isReplyMsg && m.groupChatReplyData.isNotEmpty) showReplyImage(m.groupChatReplyData, m), - 12.width, - const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), - ], - ), + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (AppState().chatDetails!.response!.userName == m.groupChatReplyData.first.currentUserName.toString() + ? "You" + : m.groupChatReplyData.first.currentUserName.toString().replaceAll(".", " ")) + .toText14(color: MyColors.lightGreenColor), + (m.groupChatReplyData.isNotEmpty ? m.groupChatReplyData.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) + ], ).expanded, + 12.width, + if (m.isReplyMsg && m.groupChatReplyData.isNotEmpty) showReplyImage(m.groupChatReplyData, m), + 12.width, + const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), ], ), - ), - if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") - SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), - const Divider(height: 1, color: MyColors.lightGreyEFColor), - if (m.isRecoding) - Column( - children: [ - Row( - children: [ - Text(m.buildTimer()).paddingAll(10), - if (m.isRecoding && m.isPlaying) - WaveBubble( - playerController: m.playerController, - isPlaying: m.playerController.playerState == PlayerState.playing, - onTap: () {}, - ).expanded - else - AudioWaveforms( - waveStyle: const WaveStyle( - waveColor: MyColors.lightGreenColor, - middleLineColor: Colors.transparent, - extendWaveform: true, - showBottom: true, - showTop: true, - waveThickness: 2, - showMiddleLine: false, - middleLineThickness: 0, - ), - padding: const EdgeInsets.all(5), - shouldCalculateScrolledPosition: false, - margin: EdgeInsets.zero, - size: const Size(double.infinity, 30.0), - recorderController: m.recorderController, - backgroundColor: Colors.white, - ).expanded, - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Icon( - Icons.delete_outlined, - size: 26, - color: MyColors.lightGreenColor, - ).paddingAll(10).onPress(() { - m.deleteRecoding(); - }), - SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) - .onPress( - () => m.sendGroupChatMessage(context, - targetUserId: params!.groupChatDetails!.groupId!, - userStatus: 0, - userEmail: "", - targetUserName: params!.groupChatDetails!.groupName!, - userList: params!.groupChatDetails!.groupUserList!), - ) - .paddingOnly(right: 21), - ], + ).expanded, + ], + ), + ), + if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") + SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), + const Divider(height: 1, color: MyColors.lightGreyEFColor), + if (m.isRecoding) + Column( + children: [ + Row( + children: [ + Text(m.buildTimer()).paddingAll(10), + if (m.isRecoding && m.isPlaying) + WaveBubble( + playerController: m.playerController, + isPlaying: m.playerController.playerState == PlayerState.playing, + onTap: () {}, + ).expanded + else + AudioWaveforms( + waveStyle: const WaveStyle( + waveColor: MyColors.lightGreenColor, + middleLineColor: Colors.transparent, + extendWaveform: true, + showBottom: true, + showTop: true, + waveThickness: 2, + showMiddleLine: false, + middleLineThickness: 0, + ), + padding: const EdgeInsets.all(5), + shouldCalculateScrolledPosition: false, + margin: EdgeInsets.zero, + size: const Size(double.infinity, 30.0), + recorderController: m.recorderController, + backgroundColor: Colors.white, + ).expanded, + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Icon( + Icons.delete_outlined, + size: 26, + color: MyColors.lightGreenColor, + ).paddingAll(10).onPress(() { + m.deleteRecoding(); + }), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) + .onPress( + () => m.sendGroupChatMessage(context, + targetUserId: params!.groupChatDetails!.groupId!, + userStatus: 0, + userEmail: "", + targetUserName: params!.groupChatDetails!.groupName!, + userList: params!.groupChatDetails!.groupUserList! + ), + ) + .paddingOnly(right: 21), + ], + ), + ], + ).objectContainerView(disablePadding: true, radius: 0), + if (!m.isRecoding) + Row( + children: [ + CustomAutoDirection( + onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL), + text: m.msgText, + child: TextField( + // textDirection: m.textDirection, + controller: m.message, + decoration: InputDecoration( + hintTextDirection: m.textDirection, + hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), + hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + filled: true, + fillColor: MyColors.white, + contentPadding: const EdgeInsets.only( + left: 21, + top: 20, + bottom: 20, ), - ], - ).objectContainerView(disablePadding: true, radius: 0), - if (!m.isRecoding) + prefixIconConstraints: const BoxConstraints(), + prefixIcon: m.sFileType.isNotEmpty + ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) + : null, + ), + onChanged: (String val) { + m.inputBoxDirection(val); + m.groupTypingInvoke(groupDetails: params!.groupChatDetails!, groupId: params!.groupChatDetails!.groupId!); + }, + ).expanded, + ), + if (m.sFileType.isNotEmpty) Row( - children: [ - CustomAutoDirection( - onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL), - text: m.msgText, - child: TextField( - // textDirection: m.textDirection, - controller: m.message, - decoration: InputDecoration( - hintTextDirection: m.textDirection, - hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), - hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - filled: true, - fillColor: MyColors.white, - contentPadding: const EdgeInsets.only( - left: 21, - top: 20, - bottom: 20, - ), - prefixIconConstraints: const BoxConstraints(), - prefixIcon: m.sFileType.isNotEmpty - ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) - : null, - ), - onChanged: (String val) { - m.inputBoxDirection(val); - m.groupTypingInvoke(groupDetails: params!.groupChatDetails!, groupId: params!.groupChatDetails!.groupId!); + children: [ + const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), + ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), + ], + ).onPress(() => m.removeAttachment()).paddingOnly(right: 15), + if (m.sFileType.isEmpty) + RotationTransition( + turns: const AlwaysStoppedAnimation(45 / 360), + child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( + () => { + m.selectImageToUpload(context) }, - ).expanded, + ), + ).paddingOnly(right: 15), + const Icon( + Icons.mic, + color: MyColors.lightGreenColor, + ).paddingOnly(right: 15).onPress(() { + m.startRecoding(context); + }), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) + .onPress( + () =>m.sendGroupChatMessage(context, + targetUserId: params!.groupChatDetails!.groupId!, + userStatus: 0, + userEmail: "", + targetUserName: params!.groupChatDetails!.groupName!, + userList: params!.groupChatDetails!.groupUserList! ), - if (m.sFileType.isNotEmpty) - Row( - children: [ - const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), - ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), - ], - ).onPress(() => m.removeAttachment()).paddingOnly(right: 15), - if (m.sFileType.isEmpty) - RotationTransition( - turns: const AlwaysStoppedAnimation(45 / 360), - child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( - () => {m.selectImageToUpload(context)}, - ), - ).paddingOnly(right: 15), - const Icon( - Icons.mic, - color: MyColors.lightGreenColor, - ).paddingOnly(right: 15).onPress(() { - m.startRecoding(context); - }), - SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) - .onPress( - () => m.sendGroupChatMessage(context, - targetUserId: params!.groupChatDetails!.groupId!, - userStatus: 0, - userEmail: "", - targetUserName: params!.groupChatDetails!.groupName!, - userList: params!.groupChatDetails!.groupUserList!), - ) - .paddingOnly(right: 21), - ], - ).objectContainerView(disablePadding: true, radius: 0), + ) + .paddingOnly(right: 21), ], - )); + ).objectContainerView(disablePadding: true, radius: 0), + ], + )); }, ), ), @@ -351,7 +355,7 @@ class _GroupChatDetailScreenState extends State { } void makeCall({required String callType}) async { - // callPro.initCallListeners(); + callPro.initCallListeners(context: context); print("================== Make call Triggered ============================"); // Map json = { // "callerID": AppState().chatDetails!.response!.id!.toString(), diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 84e6d0f..68d0029 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -18,6 +18,9 @@ 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/incoming_call_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: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_call_provider.dart'; @@ -36,6 +39,7 @@ import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; +import 'package:http/http.dart' as http; class DashboardScreen extends StatefulWidget { DashboardScreen({Key? key}) : super(key: key); @@ -209,12 +213,12 @@ class _DashboardScreenState extends State with WidgetsBindingOb } void checkERMChannel() { - data.getITGNotification().then((val) { + data.getITGNotification().then((MohemmItgResponseItem? val) { if (val!.result!.data != null) { print("-------------------- Survey ----------------------------"); if (val.result!.data!.notificationType == "Survey") { DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { + (ItgMainRes? value) { if (value!.mohemmItgResponseItem!.statusCode == 200) { if (value.mohemmItgResponseItem!.result!.data != null) { // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); @@ -230,13 +234,22 @@ class _DashboardScreenState extends State with WidgetsBindingOb } else { print("------------------------------------------- Ads --------------------"); DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { + (ItgMainRes? 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!, + // ), + // ), + // ); } } }, @@ -250,6 +263,46 @@ class _DashboardScreenState extends State with WidgetsBindingOb Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, + // appBar: AppBar( + // actions: [ + // IconButton( + // onPressed: () { + // data.getITGNotification().then((val) { + // if (val!.result!.data != null) { + // print("-------------------- Survey ----------------------------"); + // if (val.result!.data!.notificationType == "Survey") { + // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + // } else { + // print("------------------------------------------- Ads --------------------"); + // DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( + // (value) { + // if (value!.mohemmItgResponseItem!.statusCode == 200) { + // if (value.mohemmItgResponseItem!.result!.data != null) { + // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { + // "masterId": val.result!.data!.notificationMasterId, + // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, + // }); + // + // // Navigator.push( + // // context, + // // MaterialPageRoute( + // // builder: (BuildContext context) => ITGAdsScreen( + // // addMasterId: val.result!.data!.notificationMasterId!, + // // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!, + // // ), + // // ), + // // ); + // } + // } + // }, + // ); + // } + // } + // }); + // }, + // icon: Icon(Icons.add)) + // ], + // ), body: Column( children: [ Row( @@ -322,106 +375,106 @@ class _DashboardScreenState extends State with WidgetsBindingOb child: Consumer( builder: (BuildContext context, DashboardProviderModel model, Widget? child) { return (model.isAttendanceTrackingLoading - ? GetAttendanceTrackingShimmer() - : Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(15), - gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ]), - ), - child: Stack( - alignment: Alignment.center, + ? GetAttendanceTrackingShimmer() + : Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ]), + ), + child: Stack( + alignment: Alignment.center, + children: [ + if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), - Column( + LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true), + if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white), + if (model.isTimeRemainingInSeconds != 0) + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 9.height, + Directionality( + textDirection: ui.TextDirection.ltr, + child: CountdownTimer( + endTime: model.endTime, + onEnd: null, + endWidget: "00:00:00".toText14(color: Colors.white, isBold: true), + textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold), + ), + ), + LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white), + 9.height, + ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(20)), + child: LinearProgressIndicator( + value: model.progress, + minHeight: 8, + valueColor: const AlwaysStoppedAnimation(Colors.white), + backgroundColor: const Color(0xff196D73), + ), + ), + ], + ), + ], + ).paddingOnly(top: 12, right: 15, left: 12), + ), + Row( + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true), - if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white), - if (model.isTimeRemainingInSeconds != 0) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 9.height, - Directionality( - textDirection: ui.TextDirection.ltr, - child: CountdownTimer( - endTime: model.endTime, - onEnd: null, - endWidget: "00:00:00".toText14(color: Colors.white, isBold: true), - textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold), - ), - ), - LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white), - 9.height, - ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(20)), - child: LinearProgressIndicator( - value: model.progress, - minHeight: 8, - valueColor: const AlwaysStoppedAnimation(Colors.white), - backgroundColor: const Color(0xff196D73), - ), - ), - ], - ), - ], - ).paddingOnly(top: 12, right: 15, left: 12), - ), - Row( - children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.checkIn.tr().toText12(color: Colors.white), - (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) - .toString() - .toText14(color: Colors.white, isBold: true), - 4.height, - ], - ).paddingOnly(left: 12, right: 12), - ), - Container( - margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), - width: 45, - height: 45, - padding: const EdgeInsets.only(left: 10, right: 10), - decoration: BoxDecoration( - color: Color(0xff259EA4), - borderRadius: BorderRadius.only( - bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), - bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), - ), - ), - child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/biometrics.svg" : "assets/images/biometrics.svg"), - ).onPress(() { - showMyBottomSheet( - context, - callBackFunc: () {}, - child: MarkAttendanceWidget(model, isFromDashboard: true), - ); - }), - ], - ), + LocaleKeys.checkIn.tr().toText12(color: Colors.white), + (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) + .toString() + .toText14(color: Colors.white, isBold: true), + 4.height, ], + ).paddingOnly(left: 12, right: 12), + ), + Container( + margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), + width: 45, + height: 45, + padding: const EdgeInsets.only(left: 10, right: 10), + decoration: BoxDecoration( + color: Color(0xff259EA4), + borderRadius: BorderRadius.only( + bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), + ), ), - ], - ), - ).onPress( - () { - Navigator.pushNamed(context, AppRoutes.todayAttendance); - }, - )) + child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/biometrics.svg" : "assets/images/biometrics.svg"), + ).onPress(() { + showMyBottomSheet( + context, + callBackFunc: () {}, + child: MarkAttendanceWidget(model, isFromDashboard: true), + ); + }), + ], + ), + ], + ), + ], + ), + ).onPress( + () { + Navigator.pushNamed(context, AppRoutes.todayAttendance); + }, + )) .animatedSwither(); }, ), @@ -482,48 +535,48 @@ class _DashboardScreenState extends State with WidgetsBindingOb return model.isOffersLoading ? const OffersShimmerWidget() : InkWell( - onTap: () { - navigateToDetails(data.getOffersList[index]); - }, - child: SizedBox( + onTap: () { + navigateToDetails(data.getOffersList[index]); + }, + child: SizedBox( + width: 73, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( width: 73, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 73, - height: 73, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all( - Radius.circular(100), - ), - border: Border.all(color: MyColors.lightGreyE3Color, width: 1), - ), - child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - child: Hero( - tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, - transitionOnUserGestures: true, - child: Image.network( - data.getOffersList[index].logo ?? "", - fit: BoxFit.contain, - ), - ), - ), - ), - 4.height, - Expanded( - child: AppState().isArabic(context) - ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) - : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + height: 73, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), + border: Border.all(color: MyColors.lightGreyE3Color, width: 1), + ), + child: ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + child: Hero( + tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, + transitionOnUserGestures: true, + child: Image.network( + data.getOffersList[index].logo ?? "", + fit: BoxFit.contain, ), - ], + ), ), ), - ); + 4.height, + Expanded( + child: AppState().isArabic(context) + ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) + : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + ), + ], + ), + ), + ); }, separatorBuilder: (BuildContext cxt, int index) => 8.width, itemCount: 9), @@ -618,27 +671,27 @@ class _DashboardScreenState extends State with WidgetsBindingOb children: [ SvgPicture.asset("assets/icons/chat/chat.svg", color: !checkIfPrivilegedForChat() ? MyColors.lightGreyE3Color : MyColors.grey98Color - // currentIndex == 4 - // ? MyColors.grey3AColor - // : cProvider.disableChatForThisUser - // ? MyColors.lightGreyE3Color - // : MyColors.grey98Color, - ) + // currentIndex == 4 + // ? MyColors.grey3AColor + // : cProvider.disableChatForThisUser + // ? MyColors.lightGreyE3Color + // : MyColors.grey98Color, + ) .paddingAll(4), Consumer( builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { 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: data.disableChatForThisUser ? MyColors.pinkDarkColor : MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.chatUConvCounter.toString().toText10(color: Colors.white), - ), - ); + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: data.disableChatForThisUser ? MyColors.pinkDarkColor : MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.chatUConvCounter.toString().toText10(color: Colors.white), + ), + ); }, ), ], diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index e2cc999..7c3e3ec 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -98,9 +98,10 @@ class _LoginScreenState extends State with WidgetsBindingObserver { Future setupVoIPCallBacks() async { if (Platform.isIOS) { voIPKit.getVoIPToken().then((String? value) async { - print('🎈 example: setupVoIPCallBacks: $value'); + print('🎈 example: getVoIPToken: $value'); if (value != null) { - AppState().setiosVoipPlayerID = await ChatApiClient().oneSignalVoip(value); + AppState().setiosVoipPlayerID = await ChatApiClient().oneSignalVoip(value!); + print('🎈 example: OneSignal ID: ${AppState().iosVoipPlayerID}'); } }); } @@ -413,9 +414,9 @@ class _LoginScreenState extends State with WidgetsBindingObserver { Utils.showLoading(context); Future.delayed(Duration(seconds: Platform.isIOS ? 3 : 2)).whenComplete(() { if (!isIncomingCall) { + Utils.hideLoading(context); if (isAppOpenBySystem!) checkFirebaseToken(); } - Utils.hideLoading(context); }); } diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 2d755dc..31f0f85 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -96,8 +96,7 @@ class _DynamicInputScreenState extends State { SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, - arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit', - isAttachmentMandatory: dynamicParams!.isAttachmentMandatory)); + arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit',isAttachmentMandatory: dynamicParams!.isAttachmentMandatory)); if (!AppState().cancelRequestTrancsection) { return; } @@ -361,6 +360,10 @@ class _DynamicInputScreenState extends State { idColName = idColName.parseMonth(); } } + idColName = Utils.formatDateDefault(idColName!); + // commenting to test + // DateTime date = DateFormat('yyyy-MM-dd').parse(idColName!); + // idColName = DateFormat('yyyy-MM-dd HH:mm:ss').format(date); } } diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart index 5e353e8..4d6cc2c 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart @@ -77,7 +77,7 @@ class _OffersAndDiscountsDetailsState extends State { : getOffersList[0].titleEn!.toText22(isBold: true, color: const Color(0xff2B353E)).center, Html( data: AppState().isArabic(context) ? getOffersList[0].descriptionAr! : getOffersList[0].descriptionEn ?? "", - onLinkTap: (String? url, Map attributes, _) { + onLinkTap: (String? url, RenderContext context, Map attributes, _) { launchUrl(Uri.parse(url!)); }, ), diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 6f9898e..1039a9d 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -10,11 +10,14 @@ AppBar AppBarWidget(BuildContext context, bool showHomeButton = true, bool showWorkListSettingButton = false, bool showMemberButton = false, + bool isBackButton =true, List? actions, void Function()? onHomeTapped, void Function()? onBackTapped}) { return AppBar( + automaticallyImplyLeading:false, leadingWidth: 0, + leading:null, title: Row( children: [ GestureDetector( @@ -22,8 +25,8 @@ AppBar AppBarWidget(BuildContext context, onTap: Feedback.wrapForTap(() { (onBackTapped == null ? Navigator.maybePop(context) : onBackTapped()); }, context), - child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), - ), + child: const Icon(Icons.arrow_back_ios_new, color: MyColors.darkIconColor), + ) , 4.width, title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, ], diff --git a/lib/widgets/bottom_sheets/attachment_options.dart b/lib/widgets/bottom_sheets/attachment_options.dart index 30189a0..d0f4f49 100644 --- a/lib/widgets/bottom_sheets/attachment_options.dart +++ b/lib/widgets/bottom_sheets/attachment_options.dart @@ -9,7 +9,7 @@ class AttachmentOptions extends StatelessWidget { VoidCallback onGalleryTap; VoidCallback onFilesTap; bool showFilesOption; - + String pickSelection =""; AttachmentOptions({Key? key, required this.onCameraTap, required this.onGalleryTap, required this.onFilesTap, this.showFilesOption = true}) : super(key: key); @override @@ -21,6 +21,7 @@ class AttachmentOptions extends StatelessWidget { children: [ "Upload Attachment".toSectionHeading(), "Select from gallery or open camera".toText11(weight: FontWeight.w500), + GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 105 / 105, crossAxisSpacing: 9, mainAxisSpacing: 9), physics: const NeverScrollableScrollPhysics(), diff --git a/lib/widgets/chat_app_bar_widge.dart b/lib/widgets/chat_app_bar_widge.dart index cc252ec..c7630bd 100644 --- a/lib/widgets/chat_app_bar_widge.dart +++ b/lib/widgets/chat_app_bar_widge.dart @@ -13,6 +13,7 @@ AppBar ChatAppBarWidget(BuildContext context, {required String title, bool showHomeButton = true, ChatUser? chatUser, bool showTyping = false, List? actions, void Function()? onHomeTapped, void Function()? onBackTapped}) { return AppBar( leadingWidth: 0, + automaticallyImplyLeading:false, title: Consumer(builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { return Row( children: [ diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index 19b1e00..314e99b 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -11,20 +11,25 @@ import 'package:mohem_flutter_app/widgets/bottom_sheets/attachment_options.dart' import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:permission_handler/permission_handler.dart'; +final ImagePicker picker = ImagePicker(); class ImageOptions { + static void showImageOptionsNew(BuildContext context, bool showFilesOption, Function(String, File) image) { + showMyBottomSheet( context, callBackFunc: () {}, child: AttachmentOptions( showFilesOption: showFilesOption, onCameraTap: () async { + if (Platform.isAndroid) { cameraImageAndroid(image); } else { File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); - String fileName = _image.path; - var bytes = File(fileName).readAsBytesSync(); + // XFile? media = await picker.pickMedia(); + String? fileName = _image?.path; + var bytes = File(fileName!).readAsBytesSync(); String base64Encode = base64.encode(bytes); if (base64Encode != null) { image(base64Encode, _image); @@ -35,7 +40,7 @@ class ImageOptions { if (Platform.isAndroid) { galleryImageAndroid(image); } else { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await picker.pickMedia())?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -146,7 +151,7 @@ class ImageOptions { } void galleryImageAndroid(Function(String, File) image) async { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await picker.pickMedia())?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); @@ -157,7 +162,7 @@ void galleryImageAndroid(Function(String, File) image) async { } void cameraImageAndroid(Function(String, File) image) async { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); + File _image = File(( await picker.pickMedia())?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); diff --git a/pubspec.yaml b/pubspec.yaml index ddbe513..ea9fbdf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html #version: 3.3.01+300040 -version: 3.3.6+300046 +version: 3.7.7+1 environment: sdk: ">=2.16.0 <3.0.0" @@ -125,6 +125,7 @@ dependencies: #todo its for temporary purpose, later will remove this. dotted_border: ^2.0.0+3 + in_app_update: 3.0.0 flutter_ios_voip_kit: ^0.1.0