From 7c980cc353f5658f07d1540ca6d32bb324b6dc98 Mon Sep 17 00:00:00 2001 From: Aamir Date: Thu, 18 Jan 2024 17:00:42 +0300 Subject: [PATCH] Call native code android & ios --- assets/icons/chat/avi.svg | 50 +++ assets/icons/chat/flv.svg | 51 +++ assets/icons/chat/mov.svg | 54 +++ assets/icons/chat/mp4.svg | 14 + lib/api/chat/chat_api_client.dart | 9 +- lib/app_state/app_state.dart | 8 + lib/classes/chat_call_kit.dart | 15 +- lib/main.dart | 2 +- lib/provider/chat_call_provider.dart | 263 ++++++++----- lib/provider/chat_provider_model.dart | 61 +-- .../chat/call/chat_incoming_call_screen.dart | 126 +++--- .../chat/call/chat_outgoing_call_screen.dart | 10 +- lib/ui/chat/chat_bubble.dart | 108 +++-- lib/ui/chat/chat_detailed_screen.dart | 74 ++-- lib/ui/chat/chat_home.dart | 13 +- lib/ui/chat/chat_home_screen.dart | 34 +- lib/ui/chat/group_chat.dart | 191 ++++----- lib/ui/chat/group_chat_bubble.dart | 372 +++++------------- lib/ui/landing/dashboard_screen.dart | 14 +- lib/ui/login/login_screen.dart | 31 +- pubspec.yaml | 6 +- 21 files changed, 813 insertions(+), 693 deletions(-) create mode 100644 assets/icons/chat/avi.svg create mode 100644 assets/icons/chat/flv.svg create mode 100644 assets/icons/chat/mov.svg create mode 100644 assets/icons/chat/mp4.svg diff --git a/assets/icons/chat/avi.svg b/assets/icons/chat/avi.svg new file mode 100644 index 0000000..e99eaef --- /dev/null +++ b/assets/icons/chat/avi.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/flv.svg b/assets/icons/chat/flv.svg new file mode 100644 index 0000000..febd584 --- /dev/null +++ b/assets/icons/chat/flv.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/mov.svg b/assets/icons/chat/mov.svg new file mode 100644 index 0000000..22e41fe --- /dev/null +++ b/assets/icons/chat/mov.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/mp4.svg b/assets/icons/chat/mp4.svg new file mode 100644 index 0000000..5d8e9ec --- /dev/null +++ b/assets/icons/chat/mp4.svg @@ -0,0 +1,14 @@ + + + + + + + + + + 4 + + + + diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 6d325bd..7998284 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -199,6 +199,7 @@ class ChatApiClient { "${ApiConsts.getGroupByUserId}${AppState().chatDetails!.response!.id}", token: AppState().chatDetails!.response!.token, ); + if (!kReleaseMode) { logger.i("res: " + response.body); } @@ -354,7 +355,13 @@ class ChatApiClient { String id = ""; Response response = await ApiClient().postJsonForResponse( "${ApiConsts.oneSignalCall}players", - {"app_id": ApiConsts.oneSignalAppID, "identifier": value, "device_type": 0, "test_type": !kReleaseMode ? 1 : 0}, + { + "app_id": ApiConsts.oneSignalAppID, + "identifier": value, + "device_type": 0, + "test_type": !kReleaseMode ? 1 : 0 + // 1 + }, ); Map values = jsonDecode(response.body) as Map; diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 847d282..e441fa1 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -209,4 +209,12 @@ class AppState { set setisUserOnline(bool value) { _isUserOnline = value; } + + bool _isBackgroundCall = false; + + bool get isBackgroundCall => _isBackgroundCall; + + set isBackgroundCall(bool value) { + _isBackgroundCall = value; + } } diff --git a/lib/classes/chat_call_kit.dart b/lib/classes/chat_call_kit.dart index 35838a5..e4721eb 100644 --- a/lib/classes/chat_call_kit.dart +++ b/lib/classes/chat_call_kit.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_callkit_incoming/entities/entities.dart'; import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; import 'package:mohem_flutter_app/api/chat/chat_api_client.dart'; @@ -29,7 +28,6 @@ class ChatVoipCall { dynamic inCallData; bool isUserOnline = false; dynamic callData; - static const platform = MethodChannel('com.example.httpchannel/http'); Future showCallkitIncoming({required String uuid, RemoteMessage? data, CallDataModel? incomingCallData, bool background = false}) async { await FlutterCallkitIncoming.endAllCalls(); @@ -78,7 +76,7 @@ class ChatVoipCall { backgroundUrl: 'assets/test.png', actionColor: '#4CAF50', ), - ios: IOSParams( + ios: const IOSParams( iconName: 'Mohemm', handleType: '', supportsVideo: true, @@ -149,11 +147,14 @@ class ChatVoipCall { // logger.log(Level.error, "API-EVENT-END"); } - Future voipDeclineCall(IosCallPayload? _iosCallPayload) async { + Future voipDeclineCall(IosCallPayload? iosCallPayload) async { try { - ALM.UserAutoLoginModel model = await ChatApiClient().getUserCallToken(userid: _iosCallPayload!.incomingCallReciverId.toString()); - dynamic Res = await ChatApiClient() - .callDecline(cUserID: int.parse(_iosCallPayload!.incomingCallerId!), tUserID: int.parse(_iosCallPayload!.incomingCallReciverId.toString()), targetUsertoken: model.response!.token!); + print("DeclineVia Flutter"); + print(iosCallPayload!.toRawJson()); + IosCallPayload _iosCallPayload = IosCallPayload(incomingCallerId: iosCallPayload.incomingCallerId!.split("-")[0], incomingCallReciverId: iosCallPayload.incomingCallerId!.split("-")[1]); + ALM.UserAutoLoginModel model = await ChatApiClient().getUserCallToken(userid: iosCallPayload.incomingCallerId!.split("-")[1]); + await ChatApiClient() + .callDecline(cUserID: int.parse(_iosCallPayload.incomingCallerId!), tUserID: int.parse(_iosCallPayload.incomingCallReciverId.toString()), targetUsertoken: model.response!.token!); } catch (err) { print(err); } diff --git a/lib/main.dart b/lib/main.dart index 1fce2c6..9cc9a68 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:provider/single_child_widget.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:sizer/sizer.dart'; -late HubConnection chatHubConnection; +HubConnection? chatHubConnection; // test uat account // username 199067 diff --git a/lib/provider/chat_call_provider.dart b/lib/provider/chat_call_provider.dart index 0bfa728..9a2bfda 100644 --- a/lib/provider/chat_call_provider.dart +++ b/lib/provider/chat_call_provider.dart @@ -15,7 +15,6 @@ import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.da import 'package:mohem_flutter_app/models/chat/webrtc_payloads.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart'; -import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:signalr_netcore/hub_connection.dart'; class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { @@ -48,20 +47,19 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { late BuildContext providerContext; List devices = []; - var _videoDeviceId; void initCallListeners({required BuildContext context}) { providerContext = context; if (kDebugMode) { print("=================== Call Listeners Registered ======================="); } - chatHubConnection.on("OnCallAcceptedAsync", onCallAcceptedAsync); - chatHubConnection.on("OnIceCandidateAsync", onIceCandidateAsync); - chatHubConnection.on("OnOfferAsync", onOfferAsync); - chatHubConnection.on("OnAnswerOffer", onAnswerOffer); - chatHubConnection.on("OnHangUpAsync", onHangUpAsync); - chatHubConnection.on("OnCallDeclinedAsync", onCallDeclinedAsync); - // chatHubConnection.on("OnIncomingCallAsync", OnIncomingCallAsync); + chatHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync); + chatHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync); + chatHubConnection!.on("OnOfferAsync", onOfferAsync); + chatHubConnection!.on("OnAnswerOffer", onAnswerOffer); + chatHubConnection!.on("OnHangUpAsync", onHangUpAsync); + chatHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync); + // chatHubConnection!.on("OnIncomingCallAsync", OnIncomingCallAsync); } // Audio Constraints @@ -95,7 +93,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { void connectOutgoing() { isOutGoingCall = true; - notifyListeners(); + // notifyListeners(); } Future startCall({required String callType, required BuildContext context}) async { @@ -149,13 +147,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { if (isCallStarted) { isIncomingCallLoader = false; isOutGoingCall = true; - Navigator.push( + Navigator.pushReplacement( providerContext, MaterialPageRoute( builder: (BuildContext context) => StartCallPage(), - )).then((value) { - Navigator.of(providerContext).pop(); - }); + )); } } } @@ -187,7 +183,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { Future endCall({required bool isUserOnline}) async { if (isIncomingCall) { logger.i("-----------------------Endeddddd By Me---------------------------"); - if (chatHubConnection.state == HubConnectionState.Connected) { + if (chatHubConnection!.state == HubConnectionState.Connected) { await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 0); await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1); } @@ -202,7 +198,9 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { if (isCallConnected) { if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { - print("------------------ PC Stopped ----------------------------"); + if (kDebugMode) { + print("------------------ PC Stopped ----------------------------"); + } _pc.close(); _pc.dispose(); } @@ -221,7 +219,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { _localStream = null; } if (chatHubConnection != null && !isUserOnline) { - chatHubConnection.stop(); + chatHubConnection!.stop(); } await FlutterCallkitIncoming.endAllCalls(); return true; @@ -281,13 +279,26 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { } void onHangUpAsync(List? params) { - print("--------------------- onHangUp ---------------------------------------"); - + print("--------------------- onHangUp ASYNC ---------------------------------------"); + dynamic items = params!.toList(); + if (kDebugMode) { + logger.i("res: " + items.toString()); + } endCall(isUserOnline: isUserOnline).then((bool value) { - if (isCallConnected) { - Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); + if (isCallConnected && !AppState().isBackgroundCall) { + // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil((route) => false); + Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chatDetailed)); isCallConnected = false; } + if (items[0]["id"] != AppState().chatDetails!.response!.id && !AppState().isBackgroundCall) { + if (kDebugMode) { + print("Popped Due to Another User"); + } + Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); + } + if (AppState().isBackgroundCall) { + Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); + } isCallEnded = true; }); } @@ -385,17 +396,17 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { args = [debugData]; } try { - await chatHubConnection.invoke("$invokeMethod", args: args); + await chatHubConnection!.invoke("$invokeMethod", args: args); } catch (e) { logger.w(e); } } void stopListeners() async { - chatHubConnection.off('OnCallDeclinedAsync'); - chatHubConnection.off('OnCallAcceptedAsync'); - chatHubConnection.off('OnIceCandidateAsync'); - chatHubConnection.off('OnAnswerOffer'); + chatHubConnection!.off('OnCallDeclinedAsync'); + chatHubConnection!.off('OnCallAcceptedAsync'); + chatHubConnection!.off('OnIceCandidateAsync'); + chatHubConnection!.off('OnAnswerOffer'); } void playRingtone() async { @@ -439,15 +450,18 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { }, 'optional': [] }; - RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints); - await pc!.addStream(_localStream!); - pc?.onConnectionState = (RTCPeerConnectionState state) {}; - pc?.onAddStream = (MediaStream stream) { + // await pc.addStream(_localStream!); + //Changed By Aamir + _localStream?.getTracks().forEach((track) { + pc.addTrack(track, _localStream!); + }); + pc.onConnectionState = (RTCPeerConnectionState state) {}; + pc.onAddStream = (MediaStream stream) { remoteRenderer!.srcObject = stream; notifyListeners(); }; - pc!.onIceCandidate = (RTCIceCandidate e) async { + pc.onIceCandidate = (RTCIceCandidate e) async { if (isIncomingCall) { if (e.candidate != null) { var payload = {"target": incomingCallData.targetUserId, "candidate": e.toMap()}; @@ -471,7 +485,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { // remoteStream.addTrack(element); // }); // }; - pc!.onSignalingState = (RTCSignalingState state) { + pc.onSignalingState = (RTCSignalingState state) { logger.i("signaling state: " + state.name); // invoke( // invokeMethod: "InvokeMobile", @@ -479,14 +493,15 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { // targetUserID: incomingCallData.targetUserId!, // debugData: {"location": "Signaling", "parms": state.name}); }; - pc!.onIceGatheringState = (RTCIceGatheringState state) { + pc.onIceGatheringState = (RTCIceGatheringState state) { logger.i("rtc ice gathering state: " + state.name); }; - pc!.onIceConnectionState = (RTCIceConnectionState state) { + pc.onIceConnectionState = (RTCIceConnectionState state) { if (RTCIceConnectionState.RTCIceConnectionStateFailed == state || RTCIceConnectionState.RTCIceConnectionStateDisconnected == state || RTCIceConnectionState.RTCIceConnectionStateClosed == state) { logger.i("Ice Connection State:" + state.name); + // endCall().then((value) { // notifyListeners(); // }); @@ -515,7 +530,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { // } Future _createOffer() async { - RTCSessionDescription description = await _pc!.createOffer(); + RTCSessionDescription description = await _pc.createOffer(); // _offer = true; return description; } @@ -573,68 +588,92 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { Future initStreams() async { List devices = await navigator.mediaDevices.enumerateDevices(); - localVideoRenderer = RTCVideoRenderer(); remoteRenderer = RTCVideoRenderer(); + localVideoRenderer ??= RTCVideoRenderer(); await localVideoRenderer!.initialize(); - - _localStream ??= await navigator.mediaDevices.getUserMedia(isVideoCall - // ? Platform.isIOS - // ? // iOS media constraints for maximum quality camera - // { - // 'audio': true, - // 'video': { - // 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera - // 'width': { - // 'ideal': 1080, // Set the ideal width (maximum quality) - // }, - // 'height': { - // 'ideal': 1920, // Set the ideal height (maximum quality) - // }, - // 'frameRate': { - // 'ideal': 30, // Set the ideal frame rate (adjust as needed) - // }, - // }, - // } - // : // Android media constraints for maximum quality camera - // { - // 'audio': true, - // 'video': { - // 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera - // 'width': { - // 'ideal': 1920, // Set the ideal width (maximum quality) - // }, - // 'height': { - // 'ideal': 1080, // Set the ideal height (maximum quality) - // }, - // 'frameRate': { - // 'ideal': 30, // Set the ideal frame rate (adjust as needed) - // }, - // }, - // } - - ? { - "video": { - "mandatory": { - "width": {"min": 1080}, - "height": {"min": 1920} - }, - "optional": [ - {'sourceId': devices[1].deviceId}, - { - "width": {"max": 1080} - }, - {"frameRate": 30}, - {"facingMode": "user"} - ] - }, - "frameRate": 30, - "width": 1080, //420,//640,//1280, - "height": 1920, //240//480//720 - "audio": true, - } - - : audioConstraints); - localVideoRenderer!.srcObject = _localStream; + try { + _localStream = await navigator.mediaDevices.getUserMedia({ + 'audio': false, + 'video': { + 'mandatory': { + 'minWidth': '640', // Provide your own width, height and frame rate here + 'minHeight': '480', + 'minFrameRate': '30', + }, + 'facingMode': 'user', + 'optional': [], + } + }); + if (kDebugMode) { + print(_localStream..toString()); + } + localVideoRenderer!.srcObject = _localStream; + localVideoRenderer!.value = (const RTCVideoValue(width: 200, height: 200, renderVideo: true)); + print("Working localStream"); + } catch (e) { + print("Failed to get user media: $e"); + } + // _localStream = await navigator.mediaDevices.getUserMedia(isVideoCall + // ? Platform.isIOS + // ? { + // 'audio': true, + // 'video': { + // 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera + // 'width': { + // 'ideal': 1080, // Set the ideal width (maximum quality) + // }, + // 'height': { + // 'ideal': 1920, // Set the ideal height (maximum quality) + // }, + // 'frameRate': { + // 'ideal': 30, // Set the ideal frame rate (adjust as needed) + // }, + // }, + // } + // : { + // 'audio': true, + // 'video': { + // 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera + // 'width': { + // 'ideal': 1920, // Set the ideal width (maximum quality) + // }, + // 'height': { + // 'ideal': 1080, // Set the ideal height (maximum quality) + // }, + // 'frameRate': { + // 'ideal': 30, // Set the ideal frame rate (adjust as needed) + // }, + // }, + // } + // + // // ? { + // // "video": { + // // "mandatory": { + // // "width": {"min": 1080}, + // // "height": {"min": 1920} + // // }, + // // "optional": Platform.isAndroid + // // ? [ + // // {'sourceId': devices[1].deviceId}, + // // { + // // "width": {"max": 1080} + // // }, + // // {"frameRate": 30}, + // // {"facingMode": "user"} + // // ] + // // : [ + // // {"frameRate": 30}, + // // {"facingMode": "user"} + // // ] + // // }, + // // "frameRate": 30, + // // "width": 1080, //420,//640,//1280, + // // "height": 1920, //240//480//720 + // // "audio": true, + // // } + // : audioConstraints); + + // localVideoRenderer.srcObject = _localStream; await remoteRenderer!.initialize(); notifyListeners(); } @@ -661,4 +700,38 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } + + MediaRecorder? mobileRecoder; + +// void startRecording() async { +// print("=-=-=-=-=-=-= Call Recoding Started -=-=-=-=-=-=-=-=-==-="); +// if (_localStream == null) throw Exception('Stream is not initialized'); +// if (Platform.isIOS) { +// print('Recording is not available on iOS'); +// return; +// } +// Directory appDirectory = await getApplicationDocumentsDirectory(); +// String dirPath = '${appDirectory.path}/webrtc_sample'; +// if (!await Directory(dirPath).exists()) { +// await Directory(dirPath).create(); +// await File('$dirPath/.nomedia').create(); +// } +// if (appDirectory == null) throw Exception('Can\'t find storagePath'); +// String filePath = dirPath + '/mobile.mp4'; +// mobileRecoder = MediaRecorder(); +// notifyListeners(); +// MediaStreamTrack videoTrack = _localStream!.getVideoTracks().firstWhere((track) => track.kind == 'video'); +// await mobileRecoder!.start(filePath, videoTrack: videoTrack); +// +// Future.delayed(Duration(minutes: 1), () { +// stopRecording(); +// }); +// } +// +// void stopRecording() async { +// print("=-=-=-=-=-=-= Call Recoding Stopped -=-=-=-=-=-=-=-=-==-="); +// await mobileRecoder!.stop(); +// mobileRecoder = null; +// notifyListeners(); +// } } diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 8b948ff..185a05e 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -92,6 +92,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool isUserOnline = false; bool isCall = false; userLoginToken.UserAutoLoginModel userLoginData = userLoginToken.UserAutoLoginModel(); + Future getUserAutoLoginToken() async { try { userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); @@ -132,16 +133,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } catch (e) { Utils.showToast(e.toString()); } - await chatHubConnection.start(); + await chatHubConnection!.start(); if (kDebugMode) { logger.i("Hub Conn: Startedddddddd"); } - chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion); + chatHubConnection!.on("OnDeliveredChatUserAsync", onMsgReceived); + chatHubConnection!.on("OnGetChatConversationCount", onNewChatConversion); //group On message - chatHubConnection.on("OnDeliveredGroupChatHistoryAsync", onGroupMsgReceived); + chatHubConnection!.on("OnDeliveredGroupChatHistoryAsync", onGroupMsgReceived); ccProvider.initCallListeners(context: context); } @@ -155,17 +156,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void registerEvents() { - chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus); - // chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - - chatHubConnection.on("OnSubmitChatAsync", OnSubmitChatAsync); - chatHubConnection.on("OnUserTypingAsync", onUserTyping); - chatHubConnection.on("OnUserCountAsync", userCountAsync); - // chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); - chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); - chatHubConnection.on("OnGetGroupUserStatusAsync", getGroupUserStatus); - chatHubConnection.on("OnAddGroupChatHistoryAsync", groupChatHistoryAsync); + chatHubConnection!.on("OnUpdateUserStatusAsync", changeStatus); + // chatHubConnection!.on("OnDeliveredChatUserAsync", onMsgReceived); + + chatHubConnection!.on("OnSubmitChatAsync", OnSubmitChatAsync); + chatHubConnection!.on("OnUserTypingAsync", onUserTyping); + chatHubConnection!.on("OnUserCountAsync", userCountAsync); + // chatHubConnection!.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); + chatHubConnection!.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + chatHubConnection!.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + chatHubConnection!.on("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}]]} @@ -203,7 +204,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future invokeUserChatHistoryNotDeliveredAsync({required int userId}) async { - await chatHubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); + await chatHubConnection!.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); return ""; } @@ -272,7 +273,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateUserChatHistoryStatusAsync(List data) { try { - chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + chatHubConnection!.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); } catch (e) { throw e; } @@ -280,7 +281,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateUserChatHistoryOnMsg(List data) { try { - chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + chatHubConnection!.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); } catch (e) { throw e; } @@ -773,7 +774,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String chatData = '{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"$chatCID"}'; - await chatHubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); + await chatHubConnection!.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } //groupChatMessage @@ -849,7 +850,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String chatData = '{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId":$fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"groupId":$targetGroupId,"groupChatHistoryLineRequestList":${json.encode(targetUsers)},"chatReplyId": $chatReplyId,"conversationId":"${uuid.v4()}"}'; - await chatHubConnection.invoke("AddGroupChatHistoryAsync", args: [json.decode(chatData)]); + await chatHubConnection!.invoke("AddGroupChatHistoryAsync", args: [json.decode(chatData)]); } void sendGroupChatMessage( @@ -1286,7 +1287,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } bool checkFileSize(String path) { - int fileSizeLimit = 1024; + int fileSizeLimit = 5000; File f = File(path); double fileSizeInKB = f.lengthSync() / 5000; double fileSizeInMB = fileSizeInKB / 5000; @@ -1328,7 +1329,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { case ".aac": return "assets/icons/chat/aac.svg"; case ".mp3": - return "assets/icons/chat/zip.mp3"; + return "assets/icons/chat/mp3.svg"; + case ".mp4": + return "assets/icons/chat/mp4.svg"; + case ".flv": + return "assets/icons/chat/flv.svg"; + case ".avi": + return "assets/icons/chat/avi.svg"; + case ".mov": + return "assets/icons/chat/mov.svg"; default: return "assets/images/thumb.svg"; } @@ -1471,7 +1480,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { uGroups?.clear(); searchGroup?.clear(); // callP.stopListeners(); - chatHubConnection.stop(); + chatHubConnection!.stop(); AppState().chatDetails = null; } } @@ -1603,17 +1612,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future invokeChatCounter({required int userId}) async { - await chatHubConnection.invoke("GetChatCounversationCount", args: [userId]); + await chatHubConnection!.invoke("GetChatCounversationCount", args: [userId]); return ""; } void userTypingInvoke({required int currentUser, required int reciptUser}) async { - await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]); + await chatHubConnection!.invoke("UserTypingAsync", args: [reciptUser, currentUser]); } void groupTypingInvoke({required GroupResponse groupDetails, required int groupId}) async { var data = json.decode(json.encode(groupDetails.groupUserList)); - await chatHubConnection.invoke("GroupTypingAsync", args: ["${groupDetails.adminUser!.userName}", data, groupId]); + await chatHubConnection!.invoke("GroupTypingAsync", args: ["${groupDetails.adminUser!.userName}", data, groupId]); } //////// Audio Recoding Work //////////////////// diff --git a/lib/ui/chat/call/chat_incoming_call_screen.dart b/lib/ui/chat/call/chat_incoming_call_screen.dart index 8056292..3cbc473 100644 --- a/lib/ui/chat/call/chat_incoming_call_screen.dart +++ b/lib/ui/chat/call/chat_incoming_call_screen.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:io'; import 'dart:ui'; + import 'package:draggable_widget/draggable_widget.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -11,7 +12,6 @@ import 'package:flutter_webrtc/flutter_webrtc.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/consts.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/main.dart'; @@ -26,14 +26,15 @@ import 'package:provider/provider.dart'; bool isCallConnected = false; class StartCallPage extends StatefulWidget { + IosCallPayload? payload; + + StartCallPage({this.payload}); @override _StartCallPageState createState() => _StartCallPageState(); } class _StartCallPageState extends State { DragController dragController = DragController(); - bool isOutGoingCall = false; - bool isIncomingCall = false; late ChatCallProvider cProv; late ChatProviderModel provider; @@ -52,21 +53,25 @@ class _StartCallPageState extends State { dynamic calls = await FlutterCallkitIncoming.activeCalls(); if (calls.isNotEmpty) { sessionData = IncomingCallModel.fromRawJson(jsonEncode(calls[0])); - print(sessionData.toRawJson()); + if (kDebugMode) { + print(sessionData.toRawJson()); + } if (provider.isUserOnline) { + AppState().isBackgroundCall = true; cProv.isUserOnline = provider.isUserOnline; if (kDebugMode) { print("====== Processing Incoming Call in Online State ========="); } - await cProv.startIncomingCallViaKit(inCallData: sessionData!.extra!.callerDetails!.toJson(), isVCall: sessionData.extra!.callType == "video" ? true : false); + await cProv.startIncomingCallViaKit(inCallData: sessionData.extra!.callerDetails!.toJson(), isVCall: sessionData.extra!.callType == "video" ? true : false); cProv.init(); isCallConnected = true; } else { + AppState().isBackgroundCall = true; if (kDebugMode) { print("====== Processing Incoming Call ========="); } cProv.isUserOnline = provider.isUserOnline; - await cProv.startIncomingCallViaKit(inCallData: sessionData!.extra!.callerDetails!.toJson(), isVCall: sessionData.extra!.callType == "video" ? true : false); + await cProv.startIncomingCallViaKit(inCallData: sessionData.extra!.callerDetails!.toJson(), isVCall: sessionData.extra!.callType == "video" ? true : false); try { AppState().setchatUserDetails = UserAutoLoginModel(response: Response.fromJson(sessionData.extra!.loginDetails!.toJson()), errorResponses: null); await provider.buildHubConnection(context: context, ccProvider: cProv).whenComplete(() { @@ -78,20 +83,23 @@ class _StartCallPageState extends State { } } } + + // cProv.startRecording(); } void startIosCall() async { - print(await Utils.getStringFromPrefs("iosCallPayload")); - IosCallPayload _iosCallPayload = IosCallPayload.fromRawJson(await Utils.getStringFromPrefs("iosCallPayload")); - var userID = _iosCallPayload!.incomingCallReciverId; - var callType = _iosCallPayload!.incomingCallType; + // IosCallPayload? iosCallPayload = IosCallPayload.fromRawJson(await Utils.getStringFromPrefs("iosCallPayload")); + IosCallPayload? iosCallPayload = widget.payload; + var userID = iosCallPayload!.incomingCallReciverId; + var callType = iosCallPayload.incomingCallType; SingleUserChatModel inCallData = SingleUserChatModel( - targetUserName: _iosCallPayload.incomingCallerName, + targetUserName: iosCallPayload.incomingCallerName, chatEventId: 3, - targetUserId: int.parse(_iosCallPayload.incomingCallerId!), + targetUserId: int.parse(iosCallPayload.incomingCallerId!), currentUserId: int.parse(userID.toString()), ); if (provider.isUserOnline) { + AppState().isBackgroundCall = true; cProv.isUserOnline = provider.isUserOnline; if (kDebugMode) { print("====== Processing Incoming Call in Online State ========="); @@ -103,6 +111,7 @@ class _StartCallPageState extends State { if (kDebugMode) { print("====== Processing Incoming Call ========="); } + AppState().isBackgroundCall = true; cProv.isUserOnline = provider.isUserOnline; UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserCallToken(userid: userID.toString()); if (userLoginResponse.response != null) { @@ -127,22 +136,25 @@ class _StartCallPageState extends State { Widget build(BuildContext context) { cProv = context.read(); provider = context.read(); - if (Platform.isAndroid) { - startCall(); - } else if (Platform.isIOS) { - startIosCall(); + if (!cProv.isOutGoingCall) { + if (Platform.isAndroid) { + startCall(); + } else if (Platform.isIOS) { + startIosCall(); + } } + return Scaffold( extendBody: true, body: Consumer2( - builder: (BuildContext context, ChatCallProvider provider, ChatProviderModel cpm, Widget? child) { - return provider.isIncomingCallLoader + builder: (BuildContext context, ChatCallProvider prov, ChatProviderModel cpm, Widget? child) { + return prov.isIncomingCallLoader ? const SizedBox( width: double.infinity, height: double.infinity, child: Center(child: CircularProgressIndicator()), ) - : provider.isIncomingCall + : prov.isIncomingCall ? Container( width: double.infinity, height: double.infinity, @@ -150,14 +162,14 @@ class _StartCallPageState extends State { child: Stack( alignment: FractionalOffset.center, children: [ - if (!provider.isAudioCall && provider.isVideoCall) + if (!prov.isAudioCall && prov.isVideoCall) RTCVideoView( - provider.remoteRenderer!, + prov.remoteRenderer!, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, // filterQuality: FilterQuality.high, key: const Key('remote'), ), - if (provider.isVideoCall) + if (prov.isVideoCall) DraggableWidget( bottomMargin: 20, topMargin: 40, @@ -172,14 +184,14 @@ class _StartCallPageState extends State { height: 200, width: 140, child: RTCVideoView( - provider.localVideoRenderer!, + prov.localVideoRenderer!, mirror: true, // filterQuality: FilterQuality.high, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), ), ), - if (!provider.isVideoCall) + if (!prov.isVideoCall) Positioned.fill( child: ClipRect( child: BackdropFilter( @@ -219,7 +231,7 @@ class _StartCallPageState extends State { ), 10.height, Text( - provider.incomingCallData.targetUserName!, + prov.incomingCallData.targetUserName!, style: const TextStyle( fontSize: 21, decoration: TextDecoration.none, @@ -273,10 +285,10 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.loudOn(); + prov.loudOn(); }, elevation: 2.0, - fillColor: provider.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, + fillColor: prov.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), @@ -290,16 +302,16 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.camOff(); + prov.camOff(); }, elevation: 2.0, - fillColor: provider.isCamOff ? MyColors.textMixColor : Colors.grey, + fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), shape: const CircleBorder(), child: Icon( - provider.isCamOff ? Icons.videocam_off : Icons.videocam, + prov.isCamOff ? Icons.videocam_off : Icons.videocam, color: MyColors.white, size: 30.0, ), @@ -307,16 +319,16 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.switchCamera(); + prov.switchCamera(); }, elevation: 2.0, - fillColor: provider.isFrontCamera ? Colors.grey : MyColors.textMixColor, + fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor, padding: const EdgeInsets.all( 10.0, ), shape: const CircleBorder(), child: Icon( - provider.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, + prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, color: MyColors.white, size: 30.0, ), @@ -324,16 +336,16 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.micOff(); + prov.micOff(); }, elevation: 2.0, - fillColor: provider.isMicOff ? MyColors.textMixColor : Colors.grey, + fillColor: prov.isMicOff ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), shape: const CircleBorder(), child: Icon( - provider.isMicOff ? Icons.mic_off : Icons.mic, + prov.isMicOff ? Icons.mic_off : Icons.mic, color: MyColors.white, size: 30.0, ), @@ -341,10 +353,10 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.endCall(isUserOnline: cpm.isUserOnline).then((bool value) { + prov.endCall(isUserOnline: cpm.isUserOnline).then((bool value) { if (value) { Navigator.of(context).pop(); - // print("Reintiiiiiiitttiiiiiiii"); + // print("Reintiiiiiiitttiiiiiiii"); // provider.initStreams(); } }); @@ -368,7 +380,7 @@ class _StartCallPageState extends State { ], ), ) - : provider.isOutGoingCall + : prov.isOutGoingCall ? Container( width: double.infinity, height: double.infinity, @@ -376,13 +388,13 @@ class _StartCallPageState extends State { child: Stack( alignment: FractionalOffset.center, children: [ - if (!provider.isAudioCall && provider.isVideoCall) + if (!prov.isAudioCall && prov.isVideoCall) RTCVideoView( - provider.remoteRenderer!, + prov.remoteRenderer!, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, key: const Key('remote'), ), - if (provider.isVideoCall) + if (prov.isVideoCall) DraggableWidget( bottomMargin: 20, topMargin: 40, @@ -397,13 +409,13 @@ class _StartCallPageState extends State { height: 200, width: 140, child: RTCVideoView( - provider.localVideoRenderer!, + prov.localVideoRenderer!, mirror: true, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), ), ), - if (!provider.isVideoCall) + if (!prov.isVideoCall) Positioned.fill( child: ClipRect( child: BackdropFilter( @@ -443,7 +455,7 @@ class _StartCallPageState extends State { ), 10.height, Text( - provider.outGoingCallData.receiverName!, + prov.outGoingCallData.receiverName!, style: const TextStyle( fontSize: 21, decoration: TextDecoration.none, @@ -497,10 +509,10 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.loudOn(); + prov.loudOn(); }, elevation: 2.0, - fillColor: provider.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, + fillColor: prov.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), @@ -514,16 +526,16 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.camOff(); + prov.camOff(); }, elevation: 2.0, - fillColor: provider.isCamOff ? MyColors.textMixColor : Colors.grey, + fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), shape: const CircleBorder(), child: Icon( - provider.isCamOff ? Icons.videocam_off : Icons.videocam, + prov.isCamOff ? Icons.videocam_off : Icons.videocam, color: MyColors.white, size: 30.0, ), @@ -531,16 +543,16 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.switchCamera(); + prov.switchCamera(); }, elevation: 2.0, - fillColor: provider.isFrontCamera ? Colors.grey : MyColors.textMixColor, + fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor, padding: const EdgeInsets.all( 10.0, ), shape: const CircleBorder(), child: Icon( - provider.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, + prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, color: MyColors.white, size: 30.0, ), @@ -548,16 +560,16 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.micOff(); + prov.micOff(); }, elevation: 2.0, - fillColor: provider.isMicOff ? MyColors.textMixColor : Colors.grey, + fillColor: prov.isMicOff ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), shape: const CircleBorder(), child: Icon( - provider.isMicOff ? Icons.mic_off : Icons.mic, + prov.isMicOff ? Icons.mic_off : Icons.mic, color: MyColors.white, size: 30.0, ), @@ -565,7 +577,7 @@ class _StartCallPageState extends State { RawMaterialButton( constraints: const BoxConstraints(), onPressed: () { - provider.endCall(isUserOnline: cpm.isUserOnline).then((bool value) { + prov.endCall(isUserOnline: cpm.isUserOnline).then((bool value) { if (value) { Navigator.of(context).pop(); } diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart index 872c98e..c01c553 100644 --- a/lib/ui/chat/call/chat_outgoing_call_screen.dart +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -1,7 +1,5 @@ -import 'dart:convert'; import 'dart:ui'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; @@ -35,6 +33,14 @@ class _OutGoingCallState extends State { Future init() async { widget.isVideoCall ? callProvider.isVideoCall = true : callProvider.isVideoCall = false; callProvider.isOutGoingCall = true; + // IosCallPayload payload = IosCallPayload( + // incomingCallerId: widget.outGoingCallData.callerId.toString(), + // incomingCallerName: widget.outGoingCallData.callerName, + // incomingCallReciverId: widget.outGoingCallData.receiverId.toString(), + // incomingCallType: widget.outGoingCallData.callType, + // uuid: "", + // callData: widget.outGoingCallData.toRawJson()); + // await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(payload)); await callProvider.initLocalCamera(chatProvmodel: chatProvider, callData: widget.outGoingCallData, context: context); loader = false; } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 95815c1..223f38e 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -18,9 +17,9 @@ import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.da 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'; +import 'package:video_player/video_player.dart'; class ChatBubble extends StatelessWidget { ChatBubble({Key? key, required this.dateTime, required this.cItem}) : super(key: key); @@ -82,7 +81,8 @@ class ChatBubble extends StatelessWidget { } } else { Utils.showLoading(context); - Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""), fileSource:1); + 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) { @@ -195,20 +195,26 @@ class ChatBubble extends StatelessWidget { }), ), ).paddingOnly(bottom: 4), - if (fileTypeID == 13 && cItem.voiceController != null) - currentWaveBubble(context, cItem) + if (fileTypeID == 13 && cItem.voiceController != null) currentWaveBubble(context, cItem), + if (fileTypeID == 16) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + showVideoThumb(context, cItem), + Row( + children: [ + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded), + ], + ), + ], + ) else Row( children: [ - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 - // || fileTypeID == 2 - ) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) 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) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) const Icon(Icons.remove_red_eye, size: 16) ], ), Align( @@ -300,20 +306,26 @@ class ChatBubble extends StatelessWidget { }), ), ).paddingOnly(bottom: 4), - if (fileTypeID == 13 && cItem.voiceController != null) - recipetWaveBubble(context, cItem) + if (fileTypeID == 13 && cItem.voiceController != null) recipetWaveBubble(context, cItem), + if (fileTypeID == 16) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + showVideoThumb(context, cItem), + Row( + children: [ + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12(color: Colors.white).expanded), + ], + ), + ], + ) else Row( children: [ - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 - // || fileTypeID == 2 - ) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) 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) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) const Icon(Icons.remove_red_eye, color: Colors.white, size: 16) ], ), Align( @@ -324,11 +336,7 @@ class ChatBubble extends StatelessWidget { ), ], ), - ).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); - } - - Widget voiceMsg(BuildContext context) { - return Container(); + ).paddingOnly(right: MediaQuery.of(context).size.width * 0.33); } Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) { @@ -342,7 +350,7 @@ class ChatBubble extends StatelessWidget { ); } else { return FutureBuilder( - future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource:1), + future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource: 1), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.waiting) { if (snapshot.data == null) { @@ -470,4 +478,50 @@ class ChatBubble extends StatelessWidget { }, ); } + + Widget showVideoThumb(BuildContext context, SingleUserChatModel data) { + return LoadVideo(data: data); + } +} + +class LoadVideo extends StatefulWidget { + final SingleUserChatModel 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/attachments/${widget.data.fileTypeResponse?.fileName}'))..initialize().then((_) {}); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.circular(5.0), + 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/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 90f7bb2..a18b99a 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -76,7 +76,7 @@ class _ChatDetailScreenState extends State { Widget build(BuildContext context) { params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams; data = Provider.of(context, listen: false); - // callPro = Provider.of(context, listen: false); + callPro = Provider.of(context, listen: false); if (params != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), @@ -95,34 +95,34 @@ class _ChatDetailScreenState extends State { showHomeButton: false, showTyping: true, chatUser: params!.chatUser, - // actions: [ - // // if (Platform.isAndroid) - // SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() async { - // Future micPer = Permission.microphone.request(); - // if (await micPer.isGranted) { - // makeCall(callType: "AUDIO"); - // } else { - // Permission.microphone.request().isGranted.then((value) { - // makeCall(callType: "AUDIO"); - // }); - // } - // }), - // // if (Platform.isAndroid) - // 24.width, - // // if (Platform.isAndroid) - // SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() async { - // Future camPer = Permission.camera.request(); - // if (await camPer.isGranted) { - // makeCall(callType: "VIDEO"); - // } else { - // Permission.camera.request().isGranted.then((value) { - // makeCall(callType: "VIDEO"); - // }); - // } - // }), - // // if (Platform.isAndroid) - // 21.width, - // ], + actions: [ + // if (Platform.isAndroid) + SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() async { + Future micPer = Permission.microphone.request(); + if (await micPer.isGranted) { + makeCall(callType: "AUDIO"); + } else { + Permission.microphone.request().isGranted.then((value) { + makeCall(callType: "AUDIO"); + }); + } + }), + // if (Platform.isAndroid) + 24.width, + // if (Platform.isAndroid) + SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() async { + Future camPer = Permission.camera.request(); + if (await camPer.isGranted) { + makeCall(callType: "VIDEO"); + } else { + Permission.camera.request().isGranted.then((value) { + makeCall(callType: "VIDEO"); + }); + } + }), + // if (Platform.isAndroid) + 21.width, + ], ), body: SafeArea( child: Consumer( @@ -168,14 +168,16 @@ class _ChatDetailScreenState extends State { // 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.userChatHistory[i].fileTypeId! == 5 || + m.userChatHistory[i].fileTypeId! == 7 || + m.userChatHistory[i].fileTypeId! == 6 || + m.userChatHistory[i].fileTypeId! == 8 || + m.userChatHistory[i].fileTypeId! == 16) { m.getChatMedia(context, - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!, fileSource:1); + 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 f16b344..19cdd24 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; @@ -14,7 +13,6 @@ import 'package:mohem_flutter_app/ui/chat/chat_home_screen.dart'; import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/chat/group_chat.dart'; import 'package:mohem_flutter_app/ui/chat/my_team_screen.dart'; -import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; import 'package:signalr_netcore/signalr_client.dart'; @@ -48,18 +46,16 @@ class _ChatHomeState extends State { } void fetchAgain() { - if (chatHubConnection.state != HubConnectionState.Connected) { + if (chatHubConnection!.state != HubConnectionState.Connected) { data.getUserAutoLoginToken().whenComplete(() async { await data.buildHubConnection(context: context, ccProvider: callProvider); data.getUserRecentChats(); - }); return; } if (data.searchedChats == null || data.searchedChats!.isEmpty) { data.isLoading = true; - data.getUserRecentChats().whenComplete(() async { - }); + data.getUserRecentChats().whenComplete(() async {}); } } @@ -68,7 +64,6 @@ class _ChatHomeState extends State { fetchAgain(); return Scaffold( backgroundColor: MyColors.white, - appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true, isBackButton: false), body: Column( children: [ @@ -92,7 +87,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(), ], @@ -108,7 +103,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 a2c98d2..abcd9fa 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -1,7 +1,5 @@ import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -15,7 +13,6 @@ import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; -import 'package:pull_to_refresh/pull_to_refresh.dart'; class ChatHomeScreen extends StatefulWidget { const ChatHomeScreen({Key? key}) : super(key: key); @@ -154,16 +151,9 @@ class _ChatHomeScreenState extends State { alignment: Alignment.center, width: 18, height: 18, - decoration: const BoxDecoration( - color: MyColors.redColor, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), - ), - child: (m.searchedChats![index].unreadMessageCount!.toString()) - .toText10( - color: MyColors.white, - ) + decoration: const BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.all(Radius.circular(22))), + child: (m.searchedChats![index].unreadMessageCount! >= 10 ? "10+" : m.searchedChats![index].unreadMessageCount!.toString()) + .toText10(color: MyColors.white) .center, ).paddingOnly(right: 10).center, Icon( @@ -172,22 +162,14 @@ class _ChatHomeScreenState extends State { ).onPress( () { if (m.searchedChats![index].isFav == null || m.searchedChats![index].isFav == false) { - m.favoriteUser( - userID: AppState().chatDetails!.response!.id!, - targetUserID: m.searchedChats![index].id!, - fromSearch: false - ); + m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!, fromSearch: false); } else if (m.searchedChats![index].isFav == true) { m.unFavoriteUser( userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!, ); } else { - m.favoriteUser( - userID: AppState().chatDetails!.response!.id!, - targetUserID: m.searchedChats![index].id!, - fromSearch: false - ); + m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!, fromSearch: false); } }, ).center @@ -217,10 +199,10 @@ class _ChatHomeScreenState extends State { child: Container( width: 60, height: 60, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), //shape: BoxShape.circle, - gradient:const LinearGradient( + gradient: const LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, diff --git a/lib/ui/chat/group_chat.dart b/lib/ui/chat/group_chat.dart index 7c0ffde..86a1359 100644 --- a/lib/ui/chat/group_chat.dart +++ b/lib/ui/chat/group_chat.dart @@ -1,28 +1,20 @@ import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; -import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart'; import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'; import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; -import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/chat/create_group.dart'; import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart'; -import 'package:mohem_flutter_app/ui/chat/manage_group.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; -import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; -import 'package:pull_to_refresh/pull_to_refresh.dart'; class GropChatHomeScreen extends StatefulWidget { const GropChatHomeScreen({Key? key}) : super(key: key); @@ -59,26 +51,17 @@ class _GropChatHomeScreenState extends State { children: [ TextField( controller: m.searchGroup, - style: const TextStyle( - color: MyColors.darkTextColor, - fontWeight: FontWeight.w500, - fontSize: 12), + 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), + 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), + hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500, fontSize: 12), filled: true, fillColor: MyColors.greyF7Color, suffixIconConstraints: const BoxConstraints(), @@ -112,70 +95,53 @@ class _GropChatHomeScreenState extends State { padding: const EdgeInsets.all(10.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(24.0), - border: Border.all( - width: 1, color: Colors.black), + 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))!, - ]), + Column(mainAxisAlignment: MainAxisAlignment.start, children: [ + (m.uGroups![index].groupName!.toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 16)), + ]), Align( - alignment: Alignment.centerRight, - - child: PopupMenuButton( - onSelected: (String value){ - goToSelected(m.uGroups![index], m, value); - - }, - itemBuilder: (context) => [ - PopupMenuItem( - value: '1', - enabled: m.uGroups![index].isAdmin ?? false, - child: (LocaleKeys.edit - .tr() - .toText14(color: m.userGroups?.groupresponse![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor) - .paddingOnly(left: 11, top: 16))), - PopupMenuItem( - value: '2', - enabled: m.uGroups![index].isAdmin ?? false, - child: (LocaleKeys.delete - .tr() - .toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor) - .paddingOnly(left: 11, top: 16))), - PopupMenuItem( - value: '3', - enabled: m.uGroups![index].isAdmin ?? false, - onTap: () { - - }, - child: (LocaleKeys.manage - .tr() - .toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor: MyColors.lightGreyColor) - .paddingOnly(left: 11, top: 16))), - PopupMenuItem( - value: '4', - child: (LocaleKeys.members - .tr() - .toText14(color: MyColors.darkTextColor) - .paddingOnly(left: 11, top: 16))), - ], - ) - - - ) - .expanded + alignment: Alignment.centerRight, + child: PopupMenuButton( + onSelected: (String value) { + goToSelected(m.uGroups![index], m, value); + }, + itemBuilder: (context) => [ + PopupMenuItem( + value: '1', + enabled: m.uGroups![index].isAdmin ?? false, + child: (LocaleKeys.edit + .tr() + .toText14(color: m.userGroups.groupresponse![index].isAdmin == true ? MyColors.darkTextColor : MyColors.lightGreyColor) + .paddingOnly(left: 11, top: 16))), + PopupMenuItem( + value: '2', + enabled: m.uGroups![index].isAdmin ?? false, + child: (LocaleKeys.delete + .tr() + .toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor : MyColors.lightGreyColor) + .paddingOnly(left: 11, top: 16))), + PopupMenuItem( + value: '3', + enabled: m.uGroups![index].isAdmin ?? false, + onTap: () {}, + child: (LocaleKeys.manage + .tr() + .toText14(color: m.uGroups![index].isAdmin == true ? MyColors.darkTextColor : MyColors.lightGreyColor) + .paddingOnly(left: 11, top: 16))), + PopupMenuItem(value: '4', child: (LocaleKeys.members.tr().toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 16))), + ], + )).expanded ], ), ).onPress(() { - chatDetails(m.uGroups![index], m,); + chatDetails( + m.uGroups![index], + m, + ); // Navigator.pushNamed( // context, // AppRoutes.chatDetailed, @@ -187,9 +153,7 @@ class _GropChatHomeScreenState extends State { // }); }); }, - separatorBuilder: (BuildContext context, int index) => - const Divider(color: MyColors.black) - .paddingOnly(left: 59), + separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.black).paddingOnly(left: 59), ).expanded, ], ).paddingOnly(left: 21, right: 21); @@ -199,10 +163,10 @@ class _GropChatHomeScreenState extends State { child: Container( width: 60, height: 60, - decoration: BoxDecoration( + decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - // shape: BoxShape.circle, - gradient:const LinearGradient( + // shape: BoxShape.circle, + gradient: const LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, @@ -219,16 +183,15 @@ class _GropChatHomeScreenState extends State { ), ), onPressed: () async { - showMyBottomSheet( context, callBackFunc: () {}, child: CreateGroupBottomSheet( - title:LocaleKeys.addUsers.tr(), + title: LocaleKeys.addUsers.tr(), apiMode: LocaleKeys.delegate.tr(), fromChat: true, onSelectEmployee: (ReplacementList _selectedEmployee) {}, - groupDetails:GroupResponse(), + groupDetails: GroupResponse(), ), ); }, @@ -245,30 +208,32 @@ class _GropChatHomeScreenState extends State { ); } -void goToSelected(GroupResponse? groupDetails, ChatProviderModel m, String value) { - switch(value) { - case '1': + 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, + 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; - } + arguments: groupDetails, + ); + break; + case '4': + Navigator.pushNamed( + context, + AppRoutes.groupMembers, + arguments: groupDetails!.groupUserList, + ); + break; + } } - void deleteGroup( - GroupResponse? groupDetails, ChatProviderModel m, BuildContext context) { + + void deleteGroup(GroupResponse? groupDetails, ChatProviderModel m, BuildContext context) { groupDetails!.groupUserList; Utils.confirmDialog( context, @@ -281,28 +246,22 @@ void goToSelected(GroupResponse? groupDetails, ChatProviderModel m, String value } Future chatDetails(GroupResponse? groupDetails, ChatProviderModel m) async { + // await m.getGroupChatHistory(groupDetails!); - // await m.getGroupChatHistory(groupDetails!); - - Navigator.pushNamed(context, - AppRoutes.groupChatDetailed, - arguments: - GroupChatDetailedScreenParams( - groupDetails, - false)); + Navigator.pushNamed(context, AppRoutes.groupChatDetailed, arguments: GroupChatDetailedScreenParams(groupDetails, false)); } + Future editGroup(GroupResponse? groupDetails, ChatProviderModel m) async { showMyBottomSheet( context, callBackFunc: () {}, child: CreateGroupBottomSheet( - title:LocaleKeys.editGroups.tr(), + title: LocaleKeys.editGroups.tr(), apiMode: LocaleKeys.delegate.tr(), fromChat: true, onSelectEmployee: (ReplacementList _selectedEmployee) {}, groupDetails: groupDetails!, ), ); - } } diff --git a/lib/ui/chat/group_chat_bubble.dart b/lib/ui/chat/group_chat_bubble.dart index 7b3db77..e16935b 100644 --- a/lib/ui/chat/group_chat_bubble.dart +++ b/lib/ui/chat/group_chat_bubble.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -19,14 +18,12 @@ import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.da 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'; import 'package:video_player/video_player.dart'; class GroupChatBubble extends StatelessWidget { - GroupChatBubble({Key? key, required this.dateTime, required this.cItem}) - : super(key: key); + GroupChatBubble({Key? key, required this.dateTime, required this.cItem}) : super(key: key); final String dateTime; final GetGroupChatHistoryAsync cItem; @@ -53,27 +50,15 @@ class GroupChatBubble extends StatelessWidget { late Offset screenOffset; void makeAssign() { - isCurrentUser = cItem.currentUserId == AppState().chatDetails!.response!.id - ? true - : false; + 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(); + 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( @@ -82,8 +67,7 @@ class GroupChatBubble extends StatelessWidget { }) async { if (data.voice != null && data.voice!.existsSync()) { if (Platform.isIOS) { - Duration? duration = await data.voiceController! - .setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); + 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); @@ -98,13 +82,10 @@ class GroupChatBubble extends StatelessWidget { } } else { Utils.showLoading(context); - Uint8List encodedString = await ChatApiClient().downloadURL( - fileName: data.contant!, - fileTypeDescription: provider.getFileTypeDescription( - data.fileTypeResponse!.fileTypeName ?? ""), fileSource: 2); + Uint8List encodedString = + await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""), fileSource: 2); // try { - File sFile = await provider.downChatVoice( - encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); + File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); if (sFile.path.isEmpty) { logger.d("Path Is Emptyyyyyyy"); } else { @@ -113,8 +94,7 @@ class GroupChatBubble extends StatelessWidget { data.voice = sFile; if (Platform.isIOS) { logger.d("isIOS"); - Duration? duration = await data.voiceController! - .setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); + 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); @@ -122,8 +102,7 @@ class GroupChatBubble extends StatelessWidget { Utils.hideLoading(context); data.voiceController!.play(); } else { - Duration? duration = - await data.voiceController!.setFilePath(sFile.path); + Duration? duration = await data.voiceController!.setFilePath(sFile.path); await data.voiceController!.setLoopMode(LoopMode.off); await data.voiceController!.seek(duration); Utils.hideLoading(context); @@ -132,8 +111,7 @@ class GroupChatBubble extends StatelessWidget { } } - void pausePlaying(BuildContext context, - {required SingleUserChatModel data}) async { + void pausePlaying(BuildContext context, {required SingleUserChatModel data}) async { await data.voiceController!.pause(); } @@ -144,14 +122,8 @@ class GroupChatBubble extends StatelessWidget { } } - Stream get _positionDataStream => - Rx.combineLatest3( - cItem.voiceController!.positionStream, - cItem.voiceController!.bufferedPositionStream, - cItem.voiceController!.durationStream, - (Duration position, Duration bufferedPosition, Duration? duration) => - PositionData( - position, bufferedPosition, duration ?? Duration.zero)); + Stream get _positionDataStream => Rx.combineLatest3(cItem.voiceController!.positionStream, cItem.voiceController!.bufferedPositionStream, + cItem.voiceController!.durationStream, (Duration position, Duration bufferedPosition, Duration? duration) => PositionData(position, bufferedPosition, duration ?? Duration.zero)); @override Widget build(BuildContext context) { @@ -173,49 +145,26 @@ class GroupChatBubble extends StatelessWidget { width: double.infinity, decoration: BoxDecoration( border: Border( - left: BorderSide( - width: 6, - color: isCurrentUser - ? MyColors.gradiantStartColor - : MyColors.white), + left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), ), - color: isCurrentUser - ? MyColors.black.withOpacity(0.10) - : MyColors.black.withOpacity(0.30), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), ), child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (userName) - .toText12( - color: MyColors.gradiantStartColor, isBold: false) - .paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + (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) + 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) + if (cItem.groupChatReplyResponse!.fileTypeId == 12 || cItem.groupChatReplyResponse!.fileTypeId == 3 || cItem.groupChatReplyResponse!.fileTypeId == 4) ClipRRect( borderRadius: BorderRadius.circular(8.0), child: SizedBox( @@ -223,13 +172,8 @@ class GroupChatBubble extends StatelessWidget { width: 32, child: showImage( isReplyPreview: false, - fileName: - cItem.groupChatReplyResponse!.contant!, - fileTypeDescription: cItem - .groupChatReplyResponse! - .fileTypeResponse! - .fileTypeDescription ?? - "image/jpg")), + fileName: cItem.groupChatReplyResponse!.contant!, + fileTypeDescription: cItem.groupChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg")), ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16), ], ), @@ -246,52 +190,36 @@ class GroupChatBubble extends StatelessWidget { child: showImage( isReplyPreview: false, fileName: cItem.contant!, - fileTypeDescription: cItem.fileTypeResponse != null && - cItem.fileTypeResponse!.fileTypeDescription != - null - ? cItem.fileTypeResponse!.fileTypeDescription - : cItem.fileTypeResponse!.fileTypeName) + fileTypeDescription: + cItem.fileTypeResponse != null && cItem.fileTypeResponse!.fileTypeDescription != null ? cItem.fileTypeResponse!.fileTypeDescription : cItem.fileTypeResponse!.fileTypeName) .onPress(() { showDialog( context: context, anchorPoint: screenOffset, - builder: (BuildContext context) => ChatImagePreviewScreen( - imgTitle: cItem.contant!, img: cItem.image!), + builder: (BuildContext context) => ChatImagePreviewScreen(imgTitle: cItem.contant!, img: cItem.image!), ); }), ), ).paddingOnly(bottom: 4), - if (fileTypeID == 13 && cItem.voiceController != null) - currentWaveBubble(context, cItem), + if (fileTypeID == 13 && cItem.voiceController != null) currentWaveBubble(context, cItem), if (fileTypeID == 16) - showVideoThumb(context, cItem) + Column( + children: [ + showVideoThumb(context, cItem), + Row( + children: [ + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded), + ], + ), + ], + ) 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) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) + 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) const Icon(Icons.remove_red_eye, size: 16) ], ), Align( @@ -303,32 +231,24 @@ class GroupChatBubble extends StatelessWidget { color: MyColors.grey41Color.withOpacity(.5), ), 7.width, - Icon(isDelivered ? Icons.done_all : Icons.done_all, - color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, - size: 14), + 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); + ).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), + padding: const EdgeInsets.only(top: 11, left: 13, right: 13, bottom: 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), gradient: const LinearGradient( transform: GradientRotation(.83), begin: Alignment.topRight, end: Alignment.bottomLeft, - colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor - ], + colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor], ), ), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -338,51 +258,25 @@ class GroupChatBubble extends StatelessWidget { 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), + border: Border(left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white)), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), ), child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (userName) - .toText12( - color: MyColors.gradiantStartColor, - isBold: false) - .paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + (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), + 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) + if (cItem.groupChatReplyResponse!.fileTypeId == 12 || cItem.groupChatReplyResponse!.fileTypeId == 3 || cItem.groupChatReplyResponse!.fileTypeId == 4) ClipRRect( borderRadius: BorderRadius.circular(8.0), child: SizedBox( @@ -390,13 +284,8 @@ class GroupChatBubble extends StatelessWidget { width: 32, child: showImage( isReplyPreview: true, - fileName: - cItem.groupChatReplyResponse!.contant!, - fileTypeDescription: cItem - .groupChatReplyResponse! - .fileTypeResponse! - .fileTypeDescription ?? - "image/jpg"), + fileName: cItem.groupChatReplyResponse!.contant!, + fileTypeDescription: cItem.groupChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg"), ), ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16) ], @@ -411,88 +300,55 @@ class GroupChatBubble extends StatelessWidget { child: SizedBox( height: 140, width: 227, - child: showImage( - isReplyPreview: false, - fileName: cItem.contant ?? "", - fileTypeDescription: - cItem.fileTypeResponse!.fileTypeDescription ?? - "image/jpg") - .onPress(() { + 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!), + builder: (BuildContext context) => ChatImagePreviewScreen(imgTitle: cItem.contant ?? "", img: cItem.image!), ); }), ), ).paddingOnly(bottom: 4), - if (fileTypeID == 13 && cItem.voiceController != null) - recipetWaveBubble(context, cItem), + if (fileTypeID == 13 && cItem.voiceController != null) recipetWaveBubble(context, cItem), if (fileTypeID == 16) - showVideoThumb(context, cItem) - else Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - cItem.currentUserName! - .toText10( - color: Colors.black, - ) - .paddingOnly(bottom: 5), + showVideoThumb(context, cItem), 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) + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12(color: Colors.white).expanded), ], ), - Align( - alignment: Alignment.topRight, - child: dateTime - .toText10( - color: Colors.white.withOpacity(.71), - ) - .paddingOnly(top: 5), - ), ], + ) + 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(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.centerRight, + child: dateTime.toText10( + color: Colors.white.withOpacity(.71), ), - ])).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); + ), + ])).paddingOnly(right: MediaQuery.of(context).size.width * 0.33); } Widget voiceMsg(BuildContext context) { return Container(); } - Widget showImage( - {required bool isReplyPreview, - required String fileName, - required String fileTypeDescription}) { + Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) { if (cItem.isImageLoaded != null && cItem.image != null) { return Image.memory( cItem.image!, @@ -503,8 +359,7 @@ class GroupChatBubble extends StatelessWidget { ); } else { return FutureBuilder( - future: ChatApiClient().downloadURL( - fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource:2), + future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource: 2), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.waiting) { if (snapshot.data == null) { @@ -531,20 +386,14 @@ class GroupChatBubble extends StatelessWidget { } } - Widget currentWaveBubble( - BuildContext context, GetGroupChatHistoryAsync data) { + 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), + left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), ), - color: isCurrentUser - ? MyColors.black.withOpacity(0.10) - : MyColors.black.withOpacity(0.30), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), ), child: Row( children: [ @@ -552,14 +401,12 @@ class GroupChatBubble extends StatelessWidget { // getPlayer(player: data.voiceController!, modelData: data), StreamBuilder( stream: _positionDataStream, - builder: - (BuildContext context, AsyncSnapshot snapshot) { + builder: (BuildContext context, AsyncSnapshot snapshot) { PositionData? positionData = snapshot.data; return SeekBar( duration: positionData?.duration ?? Duration.zero, position: positionData?.position ?? Duration.zero, - bufferedPosition: - positionData?.bufferedPosition ?? Duration.zero, + bufferedPosition: positionData?.bufferedPosition ?? Duration.zero, onChangeEnd: data.voiceController!.seek, ).expanded; }, @@ -570,24 +417,17 @@ class GroupChatBubble extends StatelessWidget { } Widget showVideoThumb(BuildContext context, GetGroupChatHistoryAsync data) { - - return LoadVideo(data: data); + return LoadVideo(data: data); } - Widget recipetWaveBubble( - BuildContext context, GetGroupChatHistoryAsync data) { + 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), + left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), ), - color: isCurrentUser - ? MyColors.black.withOpacity(0.10) - : MyColors.black.withOpacity(0.30), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), ), child: Row( mainAxisSize: MainAxisSize.max, @@ -596,14 +436,12 @@ class GroupChatBubble extends StatelessWidget { //getPlayer(player: data.voiceController!, modelData: data), StreamBuilder( stream: _positionDataStream, - builder: - (BuildContext context, AsyncSnapshot snapshot) { + builder: (BuildContext context, AsyncSnapshot snapshot) { PositionData? positionData = snapshot.data; return SeekBar( duration: positionData?.duration ?? Duration.zero, position: positionData?.position ?? Duration.zero, - bufferedPosition: - positionData?.bufferedPosition ?? Duration.zero, + bufferedPosition: positionData?.bufferedPosition ?? Duration.zero, onChangeEnd: data.voiceController!.seek, ).expanded; }, @@ -613,16 +451,14 @@ class GroupChatBubble extends StatelessWidget { ).circle(5); } - Widget getPlayer( - {required AudioPlayer player, required SingleUserChatModel modelData}) { + Widget getPlayer({required AudioPlayer player, required SingleUserChatModel modelData}) { return StreamBuilder( stream: player.playerStateStream, builder: (BuildContext context, AsyncSnapshot snapshot) { PlayerState? playerState = snapshot.data; ProcessingState? processingState = playerState?.processingState; bool? playing = playerState?.playing; - if (processingState == ProcessingState.loading || - processingState == ProcessingState.buffering) { + if (processingState == ProcessingState.loading || processingState == ProcessingState.buffering) { return Container( margin: const EdgeInsets.all(8.0), width: 30.0, @@ -661,6 +497,7 @@ class GroupChatBubble extends StatelessWidget { class LoadVideo extends StatefulWidget { final GetGroupChatHistoryAsync data; + const LoadVideo({Key? key, required this.data}) : super(key: key); @override @@ -672,21 +509,14 @@ class _LoadVideoState extends State { @override void initState() { - videoController = VideoPlayerController.networkUrl(Uri.parse( - 'https://apiderichat.hmg.com/groupattachments/${widget.data.fileTypeResponse?.fileName}')) - ..initialize().then((_) { - - }); + 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), - ), + return ClipRRect( + borderRadius: BorderRadius.circular(5.0), child: AspectRatio( aspectRatio: videoController.value.aspectRatio, child: Stack( diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 9426020..09cfd26 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -142,7 +142,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb WidgetsBinding.instance.removeObserver(this); super.dispose(); if (!cProvider.disableChatForThisUser) { - chatHubConnection.stop(); + chatHubConnection!.stop(); } } @@ -168,16 +168,16 @@ class _DashboardScreenState extends State with WidgetsBindingOb } Future checkHubCon() async { - if (chatHubConnection.state == HubConnectionState.Connected) { - await chatHubConnection.stop(); - await chatHubConnection.start(); - } else if (chatHubConnection.state != HubConnectionState.Connected) { - await chatHubConnection.start(); + if (chatHubConnection!.state == HubConnectionState.Connected) { + await chatHubConnection!.stop(); + await chatHubConnection!.start(); + } else if (chatHubConnection!.state != HubConnectionState.Connected) { + await chatHubConnection!.start(); } } void gotoChat(BuildContext context) async { - if (chatHubConnection.state == HubConnectionState.Connected) { + if (chatHubConnection!.state == HubConnectionState.Connected) { Utils.hideLoading(context); Navigator.pushNamed(context, AppRoutes.chat); String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 2f78ff0..91e6b9e 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; @@ -99,7 +98,7 @@ class _LoginScreenState extends State with WidgetsBindingObserver { voIPKit.getVoIPToken().then((String? value) async { 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}'); } }); @@ -113,7 +112,7 @@ class _LoginScreenState extends State with WidgetsBindingObserver { Map payload, ) async { _iosCallPayload = IosCallPayload.fromJson(payload); - // _timeOut(); + _timeOut(); }; voIPKit.onDidRejectIncomingCall = ( @@ -130,7 +129,8 @@ class _LoginScreenState extends State with WidgetsBindingObserver { ) async { await connectCall(uuid: uuid, callDetails: callerId); voIPKit.acceptIncomingCall(callerState: CallStateType.calling); - voIPKit.callConnected(); + voIPKit.callConnected().then((value) => timeOutTimer.cancel()); + // Utils.showToast("Timer Cancel", longDuration: true); }; } @@ -160,17 +160,26 @@ class _LoginScreenState extends State with WidgetsBindingObserver { _iosCallPayload = IosCallPayload( uuid: uuid, incomingCallerId: callDetails.split("-")[0], incomingCallReciverId: callDetails.split("-")[1], incomingCallerName: null, incomingCallType: callDetails.split("-").last); } + // _iosCallPayload = IosCallPayload(uuid: "3423434-423423-43-53-5", incomingCallerId: "266642", incomingCallReciverId: "341682", incomingCallerName: null, incomingCallType: "video"); + if (_iosCallPayload!.incomingCallerName == null) { if (Platform.isIOS) { Utils.hideLoading(context); } - await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload)); - MaterialPageRoute pageRoute = await MaterialPageRoute(builder: (BuildContext context) => StartCallPage()); + // await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload)); + // Utils.showToast("Name Null", longDuration: true); + MaterialPageRoute pageRoute = await MaterialPageRoute( + builder: (BuildContext context) => StartCallPage( + payload: _iosCallPayload, + )); Navigator.push(context, pageRoute); } else if (AppState().getisUserOnline) { - await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload)); + // await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload)); BuildContext context = AppRoutes.navigatorKey.currentContext!; - MaterialPageRoute pageRoute = await MaterialPageRoute(builder: (BuildContext context) => StartCallPage()); + MaterialPageRoute pageRoute = await MaterialPageRoute( + builder: (BuildContext context) => StartCallPage( + payload: _iosCallPayload, + )); Navigator.push(context, pageRoute); } else { FlutterCallkitIncoming.endAllCalls(); @@ -491,7 +500,11 @@ class _LoginScreenState extends State with WidgetsBindingObserver { DefaultButton(LocaleKeys.login.tr(), () async { SystemChannels.textInput.invokeMethod('TextInput.hide'); performLogin(); - }).insideContainer + }).insideContainer, + // DefaultButton("Call", () async { + // SystemChannels.textInput.invokeMethod('TextInput.hide'); + // connectCall(); + // }).insideContainer ], ), ); diff --git a/pubspec.yaml b/pubspec.yaml index ea9fbdf..6c7b417 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -85,14 +85,14 @@ dependencies: cached_network_image: ^3.2.2 #Chat - signalr_netcore: ^1.3.3 + signalr_netcore: ^1.3.6 logging: ^1.0.1 swipe_to: ^1.0.5 #flutter_webrtc: ^0.9.34 - flutter_webrtc: ^0.9.37 + flutter_webrtc: ^0.9.47 draggable_widget: ^2.0.0 flutter_callkit_incoming: ^2.0.0+1 - camera: ^0.10.3 + camera: ^0.10.5+9 flutter_local_notifications: ^10.0.0 #firebase_analytics: any