From c4c7a91d7ba77fa02ab8e9c5af1b69728d6383bf Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 16 Apr 2023 15:11:24 +0300 Subject: [PATCH] Chat Fix & Calling --- lib/classes/chat_call_kit.dart | 196 +++++++++ lib/classes/notifications.dart | 21 +- lib/classes/voip_chat_call.dart | 188 --------- lib/provider/chat_call_provider.dart | 325 ++++++++------- lib/provider/chat_provider_model.dart | 1 - .../chat/call/chat_outgoing_call_screen.dart | 384 +++++++++--------- lib/ui/chat/call/start_call_screen.dart | 41 +- lib/ui/chat/chat_detailed_screen.dart | 44 +- 8 files changed, 618 insertions(+), 582 deletions(-) create mode 100644 lib/classes/chat_call_kit.dart delete mode 100644 lib/classes/voip_chat_call.dart diff --git a/lib/classes/chat_call_kit.dart b/lib/classes/chat_call_kit.dart new file mode 100644 index 0000000..651d006 --- /dev/null +++ b/lib/classes/chat_call_kit.dart @@ -0,0 +1,196 @@ +import 'dart:convert'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_callkit_incoming/entities/entities.dart'; +import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/chat/call.dart'; +import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as ALM; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; +import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:provider/provider.dart'; + +class ChatVoipCall { + static final ChatVoipCall _instance = ChatVoipCall._internal(); + + ChatVoipCall._internal(); + + factory ChatVoipCall() => _instance; + + late ChatProviderModel prov; + late ChatCallProvider cProv; + dynamic inCallData; + bool isUserOnline = false; + + Future showCallkitIncoming({required String uuid, RemoteMessage? data, CallDataModel? incomingCallData, bool background = false}) async { + await ChatVoipCall().listenerEvent(); + ALM.Response autoLoginData; + SingleUserChatModel callerData; + // if(!background){} + await initProviders(); + if (data!.data["user_token_response"] == null || data.data["user_token_response"].isEmpty) { + autoLoginData = ALM.Response.fromJson(AppState().getchatUserDetails!.response!.toJson()); + dynamic items = jsonDecode(data!.data["user_chat_history_response"]); + callerData = SingleUserChatModel( + targetUserId: items["CurrentUserId"], + targetUserEmail: items["CurrentUserName"], + targetUserName: items["CurrentUserEmail"], + currentUserId: autoLoginData.id, + currentUserEmail: autoLoginData.email, + currentUserName: autoLoginData.userName!.split("@").first, + chatEventId: 3); + isUserOnline = true; + } else { + autoLoginData = ALM.Response.fromJson(jsonDecode(data.data["user_token_response"])); + callerData = SingleUserChatModel.fromJson(json.decode(data!.data["user_chat_history_response"])); + } + if (data!.data["callType"] == "video") { + cProv.isVideoCall = true; + } else { + cProv.isAudioCall = true; + cProv.isVideoCall = false; + } + CallKitParams params = CallKitParams( + id: uuid, + nameCaller: callerData.targetUserName, + appName: 'Mohemm', + handle: '', + type: 0, + duration: 25000, + textAccept: 'Accept', + textDecline: 'Decline', + textMissedCall: 'Missed call', + textCallback: 'Call back', + extra: { + "loginDetails": autoLoginData.toJson(), + "callerDetails": callerData.toJson(), + }, + android: const AndroidParams( + isCustomNotification: true, + isShowLogo: false, + isShowCallback: false, + isShowMissedCallNotification: true, + ringtonePath: 'system_ringtone_default', + backgroundColor: '#0955fa', + backgroundUrl: 'assets/test.png', + actionColor: '#4CAF50', + ), + ios: IOSParams( + iconName: 'Mohemm', + handleType: '', + supportsVideo: true, + maximumCallGroups: 2, + maximumCallsPerCallGroup: 1, + audioSessionMode: 'default', + audioSessionActive: true, + audioSessionPreferredSampleRate: 38000.0, + audioSessionPreferredIOBufferDuration: 0.005, + supportsDTMF: true, + supportsHolding: true, + supportsGrouping: false, + supportsUngrouping: false, + ringtonePath: 'system_ringtone_default', + ), + ); + if (callerData.chatEventId == 3) { + await Utils.saveStringFromPrefs("isIncomingCall", "true"); + connection( + data: jsonEncode([ + {"loginDetails": autoLoginData.toJson(), "callerDetails": callerData.toJson()} + ]), + isUserOnline: isUserOnline); + await FlutterCallkitIncoming.showCallkitIncoming(params); + } + } + + Future initProviders() async { + cProv = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false); + prov = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false); + } + + void connection({required data, required bool isUserOnline}) async { + cProv.isUserOnline = isUserOnline; + if (isUserOnline) { + cProv.startIncomingCallViaKit(inCallData: data); + } else { + dynamic callData = await jsonDecode(data); + AppState().setchatUserDetails = UserAutoLoginModel( + response: Response.fromJson(callData[0]["loginDetails"]), + errorResponses: null, + ); + cProv.startIncomingCallViaKit(inCallData: data); + try { + await prov.buildHubConnection(context: AppRoutes.navigatorKey.currentContext!, ccProvider: cProv).whenComplete(() { + cProv.init(); + }); + } catch (e) { + logger.w(e); + } + } + } + +//Function(CallEvent) callback + Future listenerEvent() async { + try { + FlutterCallkitIncoming.onEvent.listen((event) async { + switch (event!.event) { + case Event.ACTION_CALL_INCOMING: + // TODO: received an incoming call + break; + case Event.ACTION_CALL_START: + // TODO: started an outgoing call + // TODO: show screen calling in Flutter + break; + case Event.ACTION_CALL_ACCEPT: + if (isUserOnline) { + cProv.init(); + } + Navigator.pushNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall); + + // Navigator.pushNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall); + break; + case Event.ACTION_CALL_DECLINE: + cProv.isIncomingCall = true; + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + cProv.endCall(); + break; + case Event.ACTION_CALL_ENDED: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + break; + case Event.ACTION_CALL_TIMEOUT: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + break; + case Event.ACTION_CALL_CALLBACK: + // TODO: only Android - click action `Call back` from missed call notification + break; + case Event.ACTION_CALL_TOGGLE_HOLD: + // TODO: only iOS + break; + case Event.ACTION_CALL_TOGGLE_MUTE: + // TODO: only iOS + break; + case Event.ACTION_CALL_TOGGLE_DMTF: + // TODO: only iOS + break; + case Event.ACTION_CALL_TOGGLE_GROUP: + // TODO: only iOS + break; + case Event.ACTION_CALL_TOGGLE_AUDIO_SESSION: + // TODO: only iOS + break; + case Event.ACTION_DID_UPDATE_DEVICE_PUSH_TOKEN_VOIP: + // TODO: only iOS + break; + } + }); + } on Exception {} + } +} diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index db59171..29073e1 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -8,7 +8,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:huawei_push/huawei_push.dart' as huawei_push; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/classes/voip_chat_call.dart'; +import 'package:mohem_flutter_app/classes/chat_call_kit.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -60,7 +60,7 @@ class AppNotifications { if (initialMessage != null) _handleMessage(initialMessage); FirebaseMessaging.onMessage.listen((RemoteMessage message) { - if (message.notification != null) _handleMessage(message); + if (message != null) _handleMessage(message); }); FirebaseMessaging.onMessageOpenedApp.listen(_handleOpenApp); @@ -116,25 +116,28 @@ class AppNotifications { void _handleMessage(RemoteMessage message) { Utils.saveStringFromPrefs("isAppOpendByChat", "false"); - logger.d("Onlyyyyy Msg"); - if (message.data.isNotEmpty && message.data["messageType"] == 'chat') { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); } else if (message.data.isNotEmpty && message.data["messageType"] == 'call') { - ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message); + if( Platform.isAndroid){ + ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message); + } } } void _handleOpenApp(RemoteMessage message) { + logger.i("Open App Message:" + message.toMap().toString()); if (message.data.isNotEmpty && message.data["messageType"] == 'chat') { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); } } + + } -AndroidNotificationChannel channel = const AndroidNotificationChannel( +AndroidNotificationChannel channel = AndroidNotificationChannel( "high_importance_channel", "High Importance Notifications", importance: Importance.high, @@ -146,6 +149,8 @@ Future backgroundMessageHandler(RemoteMessage message) async { Utils.saveStringFromPrefs("isAppOpendByChat", "false"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); } else if (message.data.isNotEmpty && message.data["messageType"] == 'call') { - ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message); + if( Platform.isAndroid) { + ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message, background: true); + } } -} +} \ No newline at end of file diff --git a/lib/classes/voip_chat_call.dart b/lib/classes/voip_chat_call.dart deleted file mode 100644 index 89468cb..0000000 --- a/lib/classes/voip_chat_call.dart +++ /dev/null @@ -1,188 +0,0 @@ -import 'dart:convert'; - -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_callkit_incoming/entities/entities.dart'; -import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; -import 'package:mohem_flutter_app/app_state/app_state.dart'; -import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; -import 'package:mohem_flutter_app/main.dart'; -import 'package:mohem_flutter_app/models/chat/call.dart'; -import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; -import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as ALM; -import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; -import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; -import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; -import 'package:provider/provider.dart'; - -class ChatVoipCall { - static final ChatVoipCall _instance = ChatVoipCall._internal(); - - ChatVoipCall._internal(); - - factory ChatVoipCall() => _instance; - - late ChatProviderModel prov; - late ChatCallProvider cProv; - dynamic inCallData; - - Future showCallkitIncoming({required String uuid, RemoteMessage? data, bool isOnline = false, CallDataModel? incomingCallData}) async { - await ChatVoipCall().listenerEvent(); - if (isOnline) { - // if (incomingCallData.chatEventId == 3) { - // await Utils.saveStringFromPrefs("isIncomingCall", "true"); - // await Utils.saveStringFromPrefs( - // "inComingCallData", - // jsonEncode([ - // { - // "loginDetails": autoLoginData.toJson(), - // "callerDetails": callerData.toJson(), - // } - // ])); - // await FlutterCallkitIncoming.showCallkitIncoming(params); - // } - } else { - await initProviders(); - SingleUserChatModel callerData = SingleUserChatModel.fromJson(jsonDecode(data!.data["user_chat_history_response"])); - ALM.Response autoLoginData = ALM.Response.fromJson(jsonDecode(data.data["user_token_response"])); - data!.data["callType"] == "video" ? cProv.isVideoCall = true : cProv.isVideoCall = false; - CallKitParams params = CallKitParams( - id: uuid, - nameCaller: callerData.targetUserName, - appName: 'Mohemm', - handle: '', - type: 0, - duration: 25000, - textAccept: 'Accept', - textDecline: 'Decline', - textMissedCall: 'Missed call', - textCallback: 'Call back', - extra: { - "loginDetails": autoLoginData.toJson(), - "callerDetails": callerData.toJson(), - }, - android: const AndroidParams( - isCustomNotification: true, - isShowLogo: false, - isShowCallback: false, - isShowMissedCallNotification: true, - ringtonePath: 'system_ringtone_default', - backgroundColor: '#0955fa', - backgroundUrl: 'assets/test.png', - actionColor: '#4CAF50', - ), - ios: IOSParams( - iconName: 'Mohemm', - handleType: '', - supportsVideo: true, - maximumCallGroups: 2, - maximumCallsPerCallGroup: 1, - audioSessionMode: 'default', - audioSessionActive: true, - audioSessionPreferredSampleRate: 38000.0, - audioSessionPreferredIOBufferDuration: 0.005, - supportsDTMF: true, - supportsHolding: true, - supportsGrouping: false, - supportsUngrouping: false, - ringtonePath: 'system_ringtone_default', - ), - ); - if (callerData.chatEventId == 3) { - await Utils.saveStringFromPrefs("isIncomingCall", "true"); - // await Utils.saveStringFromPrefs( - // "inComingCallData", - // jsonEncode([ - // { - // "loginDetails": autoLoginData.toJson(), - // "callerDetails": callerData.toJson(), - // } - // ])); - connection( - data: jsonEncode([ - {"loginDetails": autoLoginData.toJson(), "callerDetails": callerData.toJson()} - ])); - await FlutterCallkitIncoming.showCallkitIncoming(params); - } - } - } - - Future initProviders() async { - cProv = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false); - prov = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false); - } - - void connection({required data}) async { - // inCallData = await Utils.getStringFromPrefs("inComingCallData"); - dynamic callData = await jsonDecode(data); - AppState().setchatUserDetails = UserAutoLoginModel( - response: Response.fromJson(callData[0]["loginDetails"]), - errorResponses: null, - ); - cProv.startIncomingCallViaKit(inCallData: data); - try { - await prov.buildHubConnection(context: AppRoutes.navigatorKey.currentContext!, ccProvider: cProv).whenComplete(() { - cProv.init(); - }); - } catch (e) { - logger.w(e); - } - } - -//Function(CallEvent) callback - Future listenerEvent() async { - try { - FlutterCallkitIncoming.onEvent.listen((event) async { - switch (event!.event) { - case Event.ACTION_CALL_INCOMING: - // TODO: received an incoming call - break; - case Event.ACTION_CALL_START: - // TODO: started an outgoing call - // TODO: show screen calling in Flutter - break; - case Event.ACTION_CALL_ACCEPT: - Navigator.pushNamedAndRemoveUntil(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall, (_) => false); - // Navigator.pushNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall); - break; - case Event.ACTION_CALL_DECLINE: - cProv.isIncomingCall = true; - Utils.saveStringFromPrefs("isIncomingCall", "false"); - Utils.saveStringFromPrefs("inComingCallData", "null"); - cProv.endCall(); - break; - case Event.ACTION_CALL_ENDED: - Utils.saveStringFromPrefs("isIncomingCall", "false"); - Utils.saveStringFromPrefs("inComingCallData", "null"); - break; - case Event.ACTION_CALL_TIMEOUT: - Utils.saveStringFromPrefs("isIncomingCall", "false"); - Utils.saveStringFromPrefs("inComingCallData", "null"); - break; - case Event.ACTION_CALL_CALLBACK: - // TODO: only Android - click action `Call back` from missed call notification - break; - case Event.ACTION_CALL_TOGGLE_HOLD: - // TODO: only iOS - break; - case Event.ACTION_CALL_TOGGLE_MUTE: - // TODO: only iOS - break; - case Event.ACTION_CALL_TOGGLE_DMTF: - // TODO: only iOS - break; - case Event.ACTION_CALL_TOGGLE_GROUP: - // TODO: only iOS - break; - case Event.ACTION_CALL_TOGGLE_AUDIO_SESSION: - // TODO: only iOS - break; - case Event.ACTION_DID_UPDATE_DEVICE_PUSH_TOKEN_VOIP: - // TODO: only iOS - break; - } - }); - } on Exception {} - } -} diff --git a/lib/provider/chat_call_provider.dart b/lib/provider/chat_call_provider.dart index decbdd0..c593cb1 100644 --- a/lib/provider/chat_call_provider.dart +++ b/lib/provider/chat_call_provider.dart @@ -1,13 +1,12 @@ import 'dart:convert'; import 'dart:io'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:just_audio/just_audio.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/classes/voip_chat_call.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; @@ -16,7 +15,6 @@ import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/call/start_call_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:signalr_netcore/hub_connection.dart'; -import 'package:uuid/uuid.dart'; class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { ///////////////////// Web RTC Video Calling ////////////////////// @@ -33,19 +31,18 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { bool isCamOff = false; bool isCallEnded = false; bool isVideoCall = false; + bool isAudioCall = false; bool isCallStarted = false; bool isFrontCamera = true; - bool isOnIncomingCallPage = false; late SingleUserChatModel incomingCallData; /// WebRTC Connection Variables - //bool _offer = false; bool isIncomingCallLoader = true; bool isIncomingCall = false; - late BuildContext providerContext; + bool isOutGoingCall = false; + bool isUserOnline = false; - /// Temp Variable Remove After Development - var tempPayLoad; + late BuildContext providerContext; void initCallListeners({required BuildContext context}) { providerContext = context; @@ -72,11 +69,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { { "width": {"max": 1280} }, - {"frameRate": 25}, + {"frameRate": 60}, {"facingMode": "user"} ] }, - "frameRate": 25, + "frameRate": 60, "width": 1280, //420,//640,//1280, "height": 720, //240//480//720 "audio": true, @@ -98,16 +95,16 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { }); } + ///////////////////////////////////////////////OutGoing Call//////////////////////////////////////////////////// + Future initLocalCamera({required ChatProviderModel chatProvmodel, required callData, required BuildContext context, bool isIncomingCall = false}) async { isCallEnded = false; chatProvModel = chatProvmodel; outGoingCallData = callData; - await localVideoRenderer.initialize(); localStream = await navigator.mediaDevices.getUserMedia(isVideoCall ? videoConstraints : audioConstraints); localVideoRenderer.srcObject = localStream; await remoteRenderer.initialize(); - // playRingtone(); await startCall(callType: isVideoCall ? "Video" : "Audio", context: context); _pc = await creatOfferWithCon(); notifyListeners(); @@ -135,57 +132,17 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 4); } - Future endCall() async { - if (isIncomingCall) { - if (chatHubConnection.state == HubConnectionState.Connected) { - await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1); - await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1); - } - if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { - _pc.dispose(); - } - isCallStarted = false; - isVideoCall = false; - isCamOff = false; - isMicOff = false; - isLoudSpeaker = false; - localVideoRenderer.srcObject = null; - remoteRenderer.srcObject = null; - isIncomingCall = false; - return true; - } else { - if (chatHubConnection.state == HubConnectionState.Connected) { - await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1); - await invoke(invokeMethod: "HangUpAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1); - } - if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { - _pc.dispose(); - } - isCallStarted = false; - isVideoCall = false; - isCamOff = false; - isMicOff = false; - isLoudSpeaker = false; - localVideoRenderer.srcObject = null; - remoteRenderer.srcObject = null; - //player.stop(); - // _offer = false; - return true; - } - } - // OutGoing Listeners void onCallAcceptedAsync(List? params) async { - print("--------------------- On Call Accept ---------------------------------------"); dynamic items = params!.toList(); RTCSessionDescription description = await _createOffer(); await _pc.setLocalDescription(description); - var payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()}; + dynamic payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()}; invoke(invokeMethod: "OfferAsync", currentUserID: outGoingCallData.callerId!, targetUserID: items[0]["id"], data: jsonEncode(payload)); } Future onIceCandidateAsync(List? params) async { - var items = params!.toList(); + dynamic items = params!.toList(); if (isIncomingCall) { RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString())); if (_pc != null) { @@ -223,7 +180,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { _pc.setRemoteDescription(RTCSessionDescription(data[0]["sdp"]["sdp"], data[0]["sdp"]["type"])); RTCSessionDescription description = await _createAnswer(); await _pc.setLocalDescription(description); - var payload = {"target": data[0]["caller"], "caller": AppState().chatDetails!.response!.id, "sdp": description.toMap()}; + dynamic payload = {"target": data[0]["caller"], "caller": AppState().chatDetails!.response!.id, "sdp": description.toMap()}; invoke(invokeMethod: "AnswerOfferAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, data: jsonEncode(payload)); } // else { @@ -235,6 +192,59 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } + //////////////////////////// OutGoing Call End /////////////////////////////////////// + + Future endCall() async { + if (isIncomingCall) { + logger.i("-----------------------Endeddddd By Me---------------------------"); + if (chatHubConnection.state == HubConnectionState.Connected) { + await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 0); + await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 0); + } + if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { + _pc.dispose(); + } + isCallStarted = false; + isVideoCall = false; + isCamOff = false; + isMicOff = false; + isLoudSpeaker = false; + localVideoRenderer.srcObject = null; + remoteRenderer.srcObject = null; + isIncomingCall = false; + if (chatHubConnection != null) { + chatHubConnection.stop(); + } + return true; + } else { + if (isOutGoingCall) { + await invoke(invokeMethod: "HangUpAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1); + await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 0); + } else { + await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1); + } + if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { + _pc.dispose(); + } + isCallStarted = false; + isVideoCall = false; + isCamOff = false; + isMicOff = false; + isLoudSpeaker = false; + localVideoRenderer.srcObject = null; + remoteRenderer.srcObject = null; + isOutGoingCall = false; + return true; + } + } + + Future reInit() async { + await localVideoRenderer.initialize(); + localStream = await navigator.mediaDevices.getUserMedia(isVideoCall ? videoConstraints : audioConstraints); + // localVideoRenderer.srcObject = localStream; + await remoteRenderer.initialize(); + } + // Incoming Listeners void onAnswerOffer(List? payload) async { @@ -254,69 +264,73 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { void onHangUpAsync(List? params) { print("--------------------- onHangUp ---------------------------------------"); + isOutGoingCall = false; + // isEndedByCaller = true; endCall().then((bool value) { - isCallEnded = true; + Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); notifyListeners(); + isCallEnded = true; }); } - Future OnIncomingCallAsync(List? params) async { - print("--------------------- On Incoming Call ---------------------------------------"); - dynamic items = params!.toList(); - logger.d(items); - // Map json = { - // "callerID": items[0]["id"], - // "callerName": items[0]["userName"], - // "callerEmail": items[0]["email"], - // "callerTitle": items[0]["title"], - // "callerPhone": null, - // "receiverID": AppState().chatDetails!.response!.id, - // "receiverName": AppState().chatDetails!.response!.userName, - // "receiverEmail": AppState().chatDetails!.response!.email, - // "receiverTitle": AppState().chatDetails!.response!.title, - // "receiverPhone": AppState().chatDetails!.response!.phone, - // "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "), - // "callType": items[1] ? "Video" : "Audio", - // }; - // CallDataModel callData = CallDataModel.fromJson(json); - // ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), isOnline: true, incomingCallData: callData); - // - // if (!isOnIncomingCallPage) { - // Map json = { - // "callerID": items[0]["id"], - // "callerName": items[0]["userName"], - // "callerEmail": items[0]["email"], - // "callerTitle": items[0]["title"], - // "callerPhone": null, - // "receiverID": AppState().chatDetails!.response!.id, - // "receiverName": AppState().chatDetails!.response!.userName, - // "receiverEmail": AppState().chatDetails!.response!.email, - // "receiverTitle": AppState().chatDetails!.response!.title, - // "receiverPhone": AppState().chatDetails!.response!.phone, - // "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "), - // "callType": items[1] ? "Video" : "Audio", - // }; - // CallDataModel callData = CallDataModel.fromJson(json); - // await Navigator.push( - // providerContext, - // MaterialPageRoute( - // builder: (BuildContext context) => IncomingCall( - // isVideoCall: items[1] ? true : false, - // outGoingCallData: callData, - // ), - // ), - // ); - // isOnIncomingCallPage = true; - // } - } + // Future OnIncomingCallAsync(List? params) async { + // print("--------------------- On Incoming Call ---------------------------------------"); + // dynamic items = params!.toList(); + // logger.d(items); + // // Map json = { + // // "callerID": items[0]["id"], + // // "callerName": items[0]["userName"], + // // "callerEmail": items[0]["email"], + // // "callerTitle": items[0]["title"], + // // "callerPhone": null, + // // "receiverID": AppState().chatDetails!.response!.id, + // // "receiverName": AppState().chatDetails!.response!.userName, + // // "receiverEmail": AppState().chatDetails!.response!.email, + // // "receiverTitle": AppState().chatDetails!.response!.title, + // // "receiverPhone": AppState().chatDetails!.response!.phone, + // // "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "), + // // "callType": items[1] ? "Video" : "Audio", + // // }; + // // CallDataModel callData = CallDataModel.fromJson(json); + // // ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), isOnline: true, incomingCallData: callData); + // // + // // if (!isOnIncomingCallPage) { + // // Map json = { + // // "callerID": items[0]["id"], + // // "callerName": items[0]["userName"], + // // "callerEmail": items[0]["email"], + // // "callerTitle": items[0]["title"], + // // "callerPhone": null, + // // "receiverID": AppState().chatDetails!.response!.id, + // // "receiverName": AppState().chatDetails!.response!.userName, + // // "receiverEmail": AppState().chatDetails!.response!.email, + // // "receiverTitle": AppState().chatDetails!.response!.title, + // // "receiverPhone": AppState().chatDetails!.response!.phone, + // // "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "), + // // "callType": items[1] ? "Video" : "Audio", + // // }; + // // CallDataModel callData = CallDataModel.fromJson(json); + // // await Navigator.push( + // // providerContext, + // // MaterialPageRoute( + // // builder: (BuildContext context) => IncomingCall( + // // isVideoCall: items[1] ? true : false, + // // outGoingCallData: callData, + // // ), + // // ), + // // ); + // // isOnIncomingCallPage = true; + // // } + // } void onCallDeclinedAsync(List? params) { - endCall().then((bool value) { - if (value) { - isCallEnded = true; - notifyListeners(); - } - }); + print("================= On Declained ========================"); + // endCall().then((bool value) { + // if (value) { + // isCallEnded = true; + // notifyListeners(); + // } + // }); } //// Invoke Methods @@ -356,12 +370,26 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { chatHubConnection.off('OnAnswerOffer'); } - void disposeRenders() async { - await localVideoRenderer.dispose(); - localStream.dispose(); - notifyListeners(); + void playRingtone() async { + player.stop(); + await player.setVolume(1.0); + String audioAsset = ""; + if (Platform.isAndroid) { + audioAsset = "assets/audio/ring_60Sec.mp3"; + } else { + audioAsset = "assets/audio/ring_30Sec.caf"; + } + try { + await player.setAsset(audioAsset); + await player.load(); + player.play(); + } catch (e) { + print("Error: $e"); + } } + //////////////////// Web RTC Offers & Connections //////////////////////// + Future creatOfferWithCon() async { Map configuration = { "sdpSemantics": "plan-b", @@ -385,7 +413,6 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { }; RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints); - logger.w(pc.connectionState); await pc!.addStream(localStream!); pc?.onConnectionState = (RTCPeerConnectionState state) {}; pc?.onAddStream = (MediaStream stream) { @@ -420,11 +447,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { // }; pc!.onSignalingState = (RTCSignalingState state) { logger.i("signaling state: " + state.name); - invoke( - invokeMethod: "InvokeMobile", - currentUserID: AppState().getchatUserDetails!.response!.id!, - targetUserID: incomingCallData.targetUserId!, - debugData: {"location": "Signaling", "parms": state.name}); + // invoke( + // invokeMethod: "InvokeMobile", + // currentUserID: AppState().getchatUserDetails!.response!.id!, + // targetUserID: incomingCallData.targetUserId!, + // debugData: {"location": "Signaling", "parms": state.name}); }; pc!.onIceGatheringState = (RTCIceGatheringState state) { logger.i("rtc ice gathering state: " + state.name); @@ -434,10 +461,12 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { RTCIceConnectionState.RTCIceConnectionStateDisconnected == state || RTCIceConnectionState.RTCIceConnectionStateClosed == state) { logger.i("Ice Connection State:" + state.name); - endCall(); + // endCall().then((value) { + // notifyListeners(); + // }); } }; - pc!.onRenegotiationNeeded = _onRenegotiate; + // pc!.onRenegotiationNeeded = _onRenegotiate; return pc; } @@ -459,24 +488,6 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { } } - void playRingtone() async { - player.stop(); - await player.setVolume(1.0); - String audioAsset = ""; - if (Platform.isAndroid) { - audioAsset = "assets/audio/ring_60Sec.mp3"; - } else { - audioAsset = "assets/audio/ring_30Sec.caf"; - } - try { - await player.setAsset(audioAsset); - await player.load(); - player.play(); - } catch (e) { - print("Error: $e"); - } - } - Future _createOffer() async { RTCSessionDescription description = await _pc!.createOffer(); // _offer = true; @@ -489,6 +500,10 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { return description; } + //////////////////// Web RTC End Offers //////////////////// + + //////////////////// CallPage Buttons ////////////////////// + void micOff() { isMicOff = !isMicOff; localStream.getAudioTracks().forEach((track) { @@ -502,11 +517,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { localStream.getVideoTracks().forEach((track) { track.enabled = !track.enabled; }); - if (isCamOff) { - isVideoCall = false; - } else { - isVideoCall = true; - } + // if (isCamOff) { + // isVideoCall = false; + // } else { + // isVideoCall = true; + // } notifyListeners(); } @@ -528,7 +543,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - Future startIncomingCall() async { + /////////////////// End Call Page Buttons ///////////////////// + + ///////////////// Incoming Call /////////////////////////////// + + Future initStreams() async { await localVideoRenderer.initialize(); localStream = await navigator.mediaDevices.getUserMedia(isVideoCall ? videoConstraints : audioConstraints); localVideoRenderer.srcObject = localStream; @@ -538,10 +557,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { Future startIncomingCallViaKit({bool isVCall = true, required var inCallData}) async { Utils.saveStringFromPrefs("isIncomingCall", "false"); isVideoCall = isVCall; - await startIncomingCall(); + await initStreams(); isIncomingCall = true; dynamic callData = await jsonDecode(inCallData); incomingCallData = SingleUserChatModel.fromJson(callData[0]["callerDetails"]); + loudOn(); notifyListeners(); } @@ -551,4 +571,13 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { isVideoCall = true; notifyListeners(); } + +////////////////// End Incoming Call //////////////////////// + +//Extra +// void disposeRenders() async { +// await localVideoRenderer.dispose(); +// localStream.dispose(); +// notifyListeners(); +// } } diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 4e44ea9..e6ecc51 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -580,7 +580,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { msg = voiceFile!.path.split("/").last; } else { msg = message.text; - logger.w(msg); } SingleUserChatModel data = SingleUserChatModel( userChatHistoryId: 0, diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart index f38c67c..5fefa22 100644 --- a/lib/ui/chat/call/chat_outgoing_call_screen.dart +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -25,7 +25,7 @@ class OutGoingCall extends StatefulWidget { _OutGoingCallState createState() => _OutGoingCallState(); } -class _OutGoingCallState extends State{ +class _OutGoingCallState extends State { late ChatCallProvider callProvider; late ChatProviderModel chatProvider; @@ -39,219 +39,219 @@ class _OutGoingCallState extends State{ void init() { widget.isVideoCall ? callProvider.isVideoCall = true : callProvider.isVideoCall = false; + callProvider.isOutGoingCall = true; callProvider.initLocalCamera(chatProvmodel: chatProvider, callData: widget.outGoingCallData, context: context); - //callProvider.init(); } @override Widget build(BuildContext context) { return Scaffold( - body: Consumer(builder: (BuildContext context, ChatCallProvider chatcp, Widget? child) { - if (chatcp.isCallEnded) Navigator.pop(context); - return Stack( - alignment: FractionalOffset.center, - children: [ - if (widget.isVideoCall) - Positioned.fill( - child: RTCVideoView( - callProvider.localVideoRenderer, - objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, - ), - ), - Positioned.fill( - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0), - child: Container( - decoration: BoxDecoration( - color: MyColors.grey57Color.withOpacity( - 0.3, + body:Consumer(builder: (BuildContext context, ChatCallProvider chatcp, Widget? child) { + if (chatcp.isCallEnded) Navigator.pop(context); + return Stack( + alignment: FractionalOffset.center, + children: [ + if (chatcp.isVideoCall) + Positioned.fill( + child: RTCVideoView( + callProvider.localVideoRenderer, + objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - 40.height, - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: const EdgeInsets.all(21.0), - child: Container( - margin: const EdgeInsets.only( - left: 10.0, - right: 10.0, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 70, - width: 70, - fit: BoxFit.cover, - ), - 10.height, - Text( - widget.outGoingCallData.receiverName.toString().replaceAll(".", " "), - style: const TextStyle( - fontSize: 21, - fontWeight: FontWeight.bold, - color: MyColors.white, - letterSpacing: -1.26, - height: 23 / 12, - ), - ), - const Text( - "Ringing...", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color( - 0xffC6C6C6, - ), - letterSpacing: -0.48, - height: 23 / 24, - ), - ), - const SizedBox( - height: 2, - ), - ], - ), - ), + Positioned.fill( + child: ClipRect( + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0), + child: Container( + decoration: BoxDecoration( + color: MyColors.grey57Color.withOpacity( + 0.3, ), - ], - ), - // Container( - // margin: const EdgeInsets.all(21.0), - // width: MediaQuery.of(context).size.width, - // decoration: cardRadius(15.0, color: MyColors.black, elevation: null), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisSize: MainAxisSize.min, - // children: [ - // Container( - // padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 6.0), - // child: Text( - // "TranslationBase.of(context).appoInfo", - // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.white, letterSpacing: -0.64, height: 23 / 12), - // ), - // ), - // Container( - // padding: const EdgeInsets.only(left: 16.0, right: 16.0), - // child: Text( - // "widget.OutGoingCallData.appointmentdate + widget.OutGoingCallData.appointmenttime", - // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), - // ), - // ), - // Container( - // padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 21.0), - // child: Text( - // "widget.OutGoingCallData.clinicname", - // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), - // ), - // ), - // ], - // ), - // ), - const Spacer(), - Container( - margin: const EdgeInsets.only( - bottom: 70.0, - left: 49, - right: 49, ), - child: Row( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, children: [ - // if (widget.isVideoCall) - // RawMaterialButton( - // onPressed: () { - // callProvider.camOff(); - // }, - // elevation: 2.0, - // fillColor: callProvider.isCamOff ? MyColors.green2DColor : Colors.grey, - // padding: const EdgeInsets.all( - // 15.0, - // ), - // shape: const CircleBorder(), - // child: Icon( - // callProvider.isCamOff ? Icons.videocam_off : Icons.videocam, - // color: MyColors.white, - // size: 35.0, - // ), - // ) - // else - // RawMaterialButton( - // onPressed: () { - // callProvider.loudOn(); - // }, - // elevation: 2.0, - // fillColor: callProvider.isLoudSpeaker ? MyColors.green2DColor : Colors.grey, - // padding: const EdgeInsets.all( - // 15.0, - // ), - // shape: const CircleBorder(), - // child: const Icon( - // Icons.volume_up, - // color: MyColors.white, - // size: 35.0, - // ), - // ), - // RawMaterialButton( - // onPressed: () { - // callProvider.micOff(); - // }, - // elevation: 2.0, - // fillColor: callProvider.isMicOff ? MyColors.green2DColor : Colors.grey, - // padding: const EdgeInsets.all( - // 15.0, - // ), - // shape: const CircleBorder(), - // child: Icon( - // callProvider.isMicOff ? Icons.mic_off : Icons.mic, - // color: MyColors.white, - // size: 35.0, + 40.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.all(21.0), + child: Container( + margin: const EdgeInsets.only( + left: 10.0, + right: 10.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 70, + width: 70, + fit: BoxFit.cover, + ), + 10.height, + Text( + widget.outGoingCallData.receiverName.toString().replaceAll(".", " "), + style: const TextStyle( + fontSize: 21, + fontWeight: FontWeight.bold, + color: MyColors.white, + letterSpacing: -1.26, + height: 23 / 12, + ), + ), + const Text( + "Ringing...", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color( + 0xffC6C6C6, + ), + letterSpacing: -0.48, + height: 23 / 24, + ), + ), + const SizedBox( + height: 2, + ), + ], + ), + ), + ), + ], + ), + // Container( + // margin: const EdgeInsets.all(21.0), + // width: MediaQuery.of(context).size.width, + // decoration: cardRadius(15.0, color: MyColors.black, elevation: null), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // Container( + // padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 6.0), + // child: Text( + // "TranslationBase.of(context).appoInfo", + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.white, letterSpacing: -0.64, height: 23 / 12), + // ), + // ), + // Container( + // padding: const EdgeInsets.only(left: 16.0, right: 16.0), + // child: Text( + // "widget.OutGoingCallData.appointmentdate + widget.OutGoingCallData.appointmenttime", + // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), + // ), + // ), + // Container( + // padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 21.0), + // child: Text( + // "widget.OutGoingCallData.clinicname", + // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), + // ), + // ), + // ], // ), // ), - RawMaterialButton( - onPressed: () { - callProvider.endCall().then((bool value) { - if (value) { - Navigator.of(context).pop(); - } - }); - }, - elevation: 2.0, - fillColor: MyColors.redA3Color, - padding: const EdgeInsets.all( - 15.0, + const Spacer(), + Container( + margin: const EdgeInsets.only( + bottom: 70.0, + left: 49, + right: 49, ), - shape: const CircleBorder(), - child: const Icon( - Icons.call_end, - color: MyColors.white, - size: 35.0, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // if (widget.isVideoCall) + // RawMaterialButton( + // onPressed: () { + // callProvider.camOff(); + // }, + // elevation: 2.0, + // fillColor: callProvider.isCamOff ? MyColors.green2DColor : Colors.grey, + // padding: const EdgeInsets.all( + // 15.0, + // ), + // shape: const CircleBorder(), + // child: Icon( + // callProvider.isCamOff ? Icons.videocam_off : Icons.videocam, + // color: MyColors.white, + // size: 35.0, + // ), + // ) + // else + // RawMaterialButton( + // onPressed: () { + // callProvider.loudOn(); + // }, + // elevation: 2.0, + // fillColor: callProvider.isLoudSpeaker ? MyColors.green2DColor : Colors.grey, + // padding: const EdgeInsets.all( + // 15.0, + // ), + // shape: const CircleBorder(), + // child: const Icon( + // Icons.volume_up, + // color: MyColors.white, + // size: 35.0, + // ), + // ), + // RawMaterialButton( + // onPressed: () { + // callProvider.micOff(); + // }, + // elevation: 2.0, + // fillColor: callProvider.isMicOff ? MyColors.green2DColor : Colors.grey, + // padding: const EdgeInsets.all( + // 15.0, + // ), + // shape: const CircleBorder(), + // child: Icon( + // callProvider.isMicOff ? Icons.mic_off : Icons.mic, + // color: MyColors.white, + // size: 35.0, + // ), + // ), + RawMaterialButton( + onPressed: () { + callProvider.endCall().then((bool value) { + if (value) { + Navigator.of(context).pop(); + } + }); + }, + elevation: 2.0, + fillColor: MyColors.redA3Color, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.call_end, + color: MyColors.white, + size: 35.0, + ), + ), + ], ), ), ], ), ), - ], + ), ), ), - ), - ), - ), - ], - ); - }), + ], + ); + }), ); } diff --git a/lib/ui/chat/call/start_call_screen.dart b/lib/ui/chat/call/start_call_screen.dart index ab29ffa..793c2c7 100644 --- a/lib/ui/chat/call/start_call_screen.dart +++ b/lib/ui/chat/call/start_call_screen.dart @@ -1,14 +1,17 @@ import 'dart:convert'; import 'dart:core'; +import 'dart:io'; import 'dart:ui'; import 'package:draggable_widget/draggable_widget.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_webrtc/flutter_webrtc.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/main.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; @@ -25,24 +28,14 @@ class StartCallPage extends StatefulWidget { class _StartCallPageState extends State { final dragController = DragController(); - late ChatProviderModel chatProvider; - late ChatCallProvider callProvider; - var inCallData; -//userChatDetails @override void initState() { - // callProvider = Provider.of(context, listen: false); - // chatProvider = Provider.of(context, listen: false); - // connection(); super.initState(); } @override void dispose() { - if (chatHubConnection != null) { - chatHubConnection.stop(); - } super.dispose(); } @@ -70,14 +63,14 @@ class _StartCallPageState extends State { return Scaffold( extendBody: true, body: Consumer2(builder: (BuildContext context, ChatCallProvider provider, ChatProviderModel cpm, Widget? child) { + // if (provider.isEndedByCaller && Platform.isAndroid) SystemNavigator.pop(); return SizedBox( width: double.infinity, height: double.infinity, - child: provider.isVideoCall - ? Stack( + child:Stack( alignment: FractionalOffset.center, children: [ - if (provider.isVideoCall) + if(!provider.isAudioCall && provider.isVideoCall) Positioned.fill( child: RTCVideoView( provider.remoteRenderer!, @@ -203,7 +196,7 @@ class _StartCallPageState extends State { provider.loudOn(); }, elevation: 2.0, - fillColor: provider.isLoudSpeaker ? MyColors.green2DColor : Colors.grey, + fillColor: provider.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), @@ -220,7 +213,7 @@ class _StartCallPageState extends State { provider.camOff(); }, elevation: 2.0, - fillColor: provider.isCamOff ? MyColors.green2DColor : Colors.grey, + fillColor: provider.isCamOff ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), @@ -237,7 +230,7 @@ class _StartCallPageState extends State { provider.switchCamera(); }, elevation: 2.0, - fillColor: provider.isFrontCamera ? Colors.grey : MyColors.green2DColor, + fillColor: provider.isFrontCamera ? Colors.grey : MyColors.textMixColor, padding: const EdgeInsets.all( 10.0, ), @@ -254,7 +247,7 @@ class _StartCallPageState extends State { provider.micOff(); }, elevation: 2.0, - fillColor: provider.isMicOff ? MyColors.green2DColor : Colors.grey, + fillColor: provider.isMicOff ? MyColors.textMixColor : Colors.grey, padding: const EdgeInsets.all( 10.0, ), @@ -292,14 +285,14 @@ class _StartCallPageState extends State { ), ], ) - : const SizedBox( - width: double.infinity, - height: 500, - child: Center( - child: CircularProgressIndicator(), - ), - )); + ); }), ); } } + +/// if (Platform.isAndroid) { +// SystemNavigator.pop(); +// } else if (Platform.isIOS) { +// exit(0); +// } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 328ddd4..43d0187 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'dart:convert'; +import 'dart:io'; import 'package:audio_waveforms/audio_waveforms.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -96,28 +96,30 @@ class _ChatDetailScreenState extends State { showTyping: true, chatUser: params!.chatUser, actions: [ - 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) { + 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"); - }); - } - }), - 24.width, - 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) { + } 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"); - }); - } - }), - 21.width, + } else { + Permission.camera.request().isGranted.then((value) { + makeCall(callType: "VIDEO"); + }); + } + }), + if (Platform.isAndroid) 21.width, ], ), body: SafeArea(