You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1201 lines
46 KiB
Dart
1201 lines
46 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:diplomaticquarterapp/locator.dart';
|
|
import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart';
|
|
import 'package:diplomaticquarterapp/routes.dart';
|
|
import 'package:diplomaticquarterapp/uitl/navigation_service.dart';
|
|
import 'package:diplomaticquarterapp/uitl/utils.dart';
|
|
import 'package:diplomaticquarterapp/voipcall/call/chat_incoming_call_screen.dart';
|
|
import 'package:diplomaticquarterapp/voipcall/model/call.dart';
|
|
import 'package:diplomaticquarterapp/voipcall/model/webrtc_payloads.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
|
import 'package:http/http.dart';
|
|
import 'package:just_audio/just_audio.dart';
|
|
import 'package:logger/logger.dart' as log;
|
|
import 'package:logging/logging.dart';
|
|
import 'package:signalr_netcore/signalr_client.dart';
|
|
|
|
class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|
///////////////////// Web RTC Video Calling //////////////////////
|
|
// Video Call
|
|
HubConnection? chatHubConnection;
|
|
RTCPeerConnection? _pc;
|
|
|
|
//late ChatProviderModel chatProvModel;
|
|
RTCVideoRenderer? localVideoRenderer;
|
|
RTCVideoRenderer? remoteRenderer;
|
|
|
|
final AudioPlayer player = AudioPlayer();
|
|
MediaStream? _localStream;
|
|
CallDataModel? outGoingCallData;
|
|
bool isMicOff = false;
|
|
bool isLoudSpeaker = false;
|
|
bool isCamOff = false;
|
|
bool isCallEnded = false;
|
|
|
|
// This need to Be Changed to dynamic
|
|
bool isVideoCall = true;
|
|
bool isAudioCall = false;
|
|
bool isCallStarted = false;
|
|
bool isFrontCamera = true;
|
|
|
|
//SingleUserChatModel? incomingCallData;
|
|
|
|
/// WebRTC Connection Variables
|
|
bool isIncomingCallLoader = true;
|
|
bool isIncomingCall = false;
|
|
bool isOutGoingCall = false;
|
|
bool isUserOnline = false;
|
|
|
|
List<MediaDeviceInfo> devices = [];
|
|
log.Logger debuglogger = log.Logger();
|
|
|
|
IncomingCallData? _incomingCallData;
|
|
|
|
IncomingCallData? get incomingCallData => _incomingCallData;
|
|
|
|
set incomingCallData(IncomingCallData? value) {
|
|
_incomingCallData = value;
|
|
}
|
|
|
|
//
|
|
// // If you want only to log out the message for the higer level hub protocol:
|
|
// final hubProtLogger = Logger("SignalR - hub");
|
|
// final transportProtLogger = Logger("SignalR - transport");
|
|
// late Logger _logger;
|
|
// late StreamSubscription<LogRecord> _logMessagesSub;
|
|
//
|
|
// void _handleLogMessage(LogRecord msg) {
|
|
// print(msg.message);
|
|
// }
|
|
//
|
|
// Future<void> buildHubConnection() async {
|
|
// try {
|
|
// Logger.root.level = Level.ALL;
|
|
// _logMessagesSub = Logger.root.onRecord.listen(_handleLogMessage);
|
|
// _logger = Logger("ChatPageViewModel");
|
|
//
|
|
// // chatHubConnection = await getHubConnection();
|
|
// String to = "ytvF4zQfUrJHOUfpE7UE1Q";
|
|
// HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true, logger: transportProtLogger);
|
|
// // hub = HubConnectionBuilder()
|
|
// // .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
|
|
// // .withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
|
|
// var urlWithParams = "https://ms.hmg.com/livecare/liveCareHub?UserID=4767770&ProjectId=12&IsAdmin=false&To=$to";
|
|
// print("ChatHubURL:::: " + urlWithParams);
|
|
// chatHubConnection = await HubConnectionBuilder().withUrl(urlWithParams, options: httpOp).build();
|
|
// await chatHubConnection!.start();
|
|
// print(chatHubConnection!.state);
|
|
// chatHubConnection!.onclose(({error}) {
|
|
// print("Connection Closed");
|
|
// });
|
|
// // if (chatHubConnection!.state == HubConnectionState.Connected) {
|
|
// // print("Success Chat Con ID::: " + chatHubConnection!.connectionId.toString());
|
|
// // if (kDebugMode) {
|
|
// // print("Hub Conn: Startedddddddd");
|
|
// // }
|
|
// // //registerCallListners();
|
|
// // }
|
|
// } catch (e) {
|
|
// print(e.toString());
|
|
// Utils.showErrorToast(e.toString());
|
|
// }
|
|
// }
|
|
|
|
//{"id":341682,"userName":"Aamir.Muhammad","email":"Aamir.Muhammad@cloudsolutions.com.sa","phone":null,"title":"Aamir Saleem Ahmad Dost Muhammad","token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIzNDE2ODIiLCJlbWFpbCI6IkFhbWlyLk11aGFtbWFkQGNsb3Vkc29sdXRpb25zLmNvbS5zYSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvdXNlcmRhdGEiOiJBYW1pci5NdWhhbW1hZCIsIm5iZiI6MTcwNzIwNTAyMywiZXhwIjoxNzA3MjkxNDIzLCJpYXQiOjE3MDcyMDUwMjN9.Zz2bcsMwiLAAWGZh2E_p5Qs6ItMt0JHhDFI_0DLdggCQtt6HHcT4n8nvqMZx-uYr3jLwqhA_IAjTuaCeSE15sw","isDomainUser":true,"isActiveCode":false,"encryptedUserId":"nn7RkYzbnQc=","encryptedUserName":"/QruOyp4QMcmNXKZlljUgg=="}
|
|
// Future<HubConnection> getHubConnection() async {
|
|
// AppState().chatDetails = getUserToken.UserAutoLoginModel(
|
|
// response: getUserToken.Response.fromJson({
|
|
// "id": 341682,
|
|
// "userName": "Aamir.Muhammad",
|
|
// "email": "Aamir.Muhammad@cloudsolutions.com.sa",
|
|
// "phone": null,
|
|
// "title": "Aamir Saleem Ahmad Dost Muhammad",
|
|
// "token":
|
|
// "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIzNDE2ODIiLCJlbWFpbCI6IkFhbWlyLk11aGFtbWFkQGNsb3Vkc29sdXRpb25zLmNvbS5zYSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvdXNlcmRhdGEiOiJBYW1pci5NdWhhbW1hZCIsIm5iZiI6MTcwODI1NjI5NywiZXhwIjoxNzA4MzQyNjk3LCJpYXQiOjE3MDgyNTYyOTd9.Y-QDVbSbPzcMVkHyIT06WgM0EsKH183hASZrIsXGkFOR_XZcqCJS-CrgdN0nOtxCWV6wd01dgfhMTNTZhybwiQ",
|
|
// "isDomainUser": true,
|
|
// "isActiveCode": false,
|
|
// "encryptedUserId": "nn7RkYzbnQc=",
|
|
// "encryptedUserName": "/QruOyp4QMcmNXKZlljUgg=="
|
|
// }),
|
|
// );
|
|
// String to = "dfK3ZqFD-BTlJLnuf1F5Cw";
|
|
// HubConnection hub;
|
|
// HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
|
|
// // hub = HubConnectionBuilder()
|
|
// // .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
|
|
// // .withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
|
|
// var urlWithParams = "https://ms.hmg.com/livecare/liveCareHub?UserID=4767770&ProjectId=15&IsAdmin=false&To=$to";
|
|
// print("ChatHubURL:::: " + urlWithParams);
|
|
// hub = await HubConnectionBuilder().withUrl(urlWithParams, options: httpOp).withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
|
|
// return hub;
|
|
// }
|
|
|
|
// Future<CallDataModel> makeCall({required String callType}) async {
|
|
// Map<String, dynamic> json = {
|
|
// "callerID": AppState().chatDetails!.response!.id,
|
|
// "callerName": AppState().chatDetails!.response!.userName,
|
|
// "callerEmail": AppState().chatDetails!.response!.email,
|
|
// "callerTitle": AppState().chatDetails!.response!.title,
|
|
// "callerPhone": AppState().chatDetails!.response!.phone,
|
|
// "receiverID": 266642,
|
|
// "receiverName": "Muhammad Alam",
|
|
// "receiverEmail": "Muhamad.Alam@cloudsolutions.com.sa",
|
|
// "receiverTitle": "Muhammad Alam",
|
|
// "receiverPhone": "123456789",
|
|
// "title": "Muhammad Alam",
|
|
// "callType": callType == "VIDEO" ? "Video" : "Audio",
|
|
// };
|
|
// CallDataModel res = CallDataModel.fromJson(json);
|
|
// return res;
|
|
// }
|
|
|
|
// void registerCallListners() {
|
|
// 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);
|
|
// }
|
|
|
|
// Audio Constraints
|
|
Map<String, Object> audioConstraints = {
|
|
"sampleRate": 8000,
|
|
"sampleSize": 16,
|
|
"channelCount": 2,
|
|
"echoCancellation": true,
|
|
"audio": true,
|
|
};
|
|
|
|
// Future<void> init() async {
|
|
// _pc = await creatOfferWithCon();
|
|
// Future.delayed(const Duration(seconds: 2), () {
|
|
// connectIncomingCall();
|
|
// });
|
|
// }
|
|
|
|
///////////////////////////////////////////////OutGoing Call////////////////////////////////////////////////////
|
|
//
|
|
// Future<void> initLocalCamera({callData, bool isIncomingCall = false}) async {
|
|
// isCallEnded = false;
|
|
// outGoingCallData = callData;
|
|
// await initStreams();
|
|
// await startCall();
|
|
// _pc = await creatOfferWithCon();
|
|
// connectOutgoing();
|
|
// notifyListeners();
|
|
// }
|
|
//
|
|
// void connectOutgoing() {
|
|
// isOutGoingCall = true;
|
|
// // notifyListeners();
|
|
// }
|
|
//
|
|
// Future<void> startCall() async {
|
|
// // chatProvModel.isTextMsg = true;
|
|
// // chatProvModel.isAttachmentMsg = false;
|
|
// // chatProvModel.isVoiceMsg = false;
|
|
// // chatProvModel.isReplyMsg = false;
|
|
// // chatProvModel.isCall = true;
|
|
// // chatProvModel.message.text = "Start $callType call ${outGoingCallData.receiverName.toString().replaceAll(".", " ")}";
|
|
// // chatProvModel.sendChatMessage(
|
|
// // context,
|
|
// // targetUserId: outGoingCallData.receiverId,
|
|
// // userStatus: 1,
|
|
// // userEmail: outGoingCallData.receiverEmail,
|
|
// // targetUserName: outGoingCallData.receiverName,
|
|
// // );
|
|
// await invoke(
|
|
// invokeMethod: "CallUserAsync",
|
|
// currentUserID: outGoingCallData!.callerId!,
|
|
// targetUserID: outGoingCallData!.receiverId!,
|
|
// );
|
|
// await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData!.callerId!, targetUserID: outGoingCallData!.receiverId!, userStatus: 4);
|
|
// }
|
|
|
|
// // OutGoing Listeners
|
|
// void onCallAcceptedAsync(List<Object?>? params) async {
|
|
// dynamic items = params!.toList();
|
|
// RTCSessionDescription description = await _createOffer();
|
|
// await _pc!.setLocalDescription(description);
|
|
// 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<void> onIceCandidateAsync(List<Object?>? params) async {
|
|
// dynamic items = params!.toList();
|
|
// if (isIncomingCall) {
|
|
// RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString()));
|
|
// if (_pc != null) {
|
|
// await _pc!.addCandidate(RTCIceCandidate(data.candidate!.candidate, data.candidate!.sdpMid, data.candidate!.sdpMLineIndex));
|
|
// }
|
|
// } else {
|
|
// if (kDebugMode) {
|
|
// print("res: " + items.toString());
|
|
// }
|
|
// RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString()));
|
|
// if (_pc != null) {
|
|
// await _pc!.addCandidate(RTCIceCandidate(data.candidate!.candidate, data.candidate!.sdpMid, data.candidate!.sdpMLineIndex));
|
|
// if (!isCallStarted) {
|
|
// isCallStarted = true;
|
|
// notifyListeners();
|
|
// if (isCallStarted) {
|
|
// isIncomingCallLoader = false;
|
|
// isOutGoingCall = true;
|
|
// if (Platform.isIOS) {
|
|
// Future.delayed(Duration(seconds: 2), () {
|
|
// Navigator.pushReplacement(
|
|
// locator<NavigationService>().navigatorKey.currentContext!,
|
|
// MaterialPageRoute(
|
|
// builder: (BuildContext context) => StartCallPage(),
|
|
// ));
|
|
// });
|
|
// } else {
|
|
// Navigator.pushReplacement(
|
|
// locator<NavigationService>().navigatorKey.currentContext!,
|
|
// MaterialPageRoute(
|
|
// builder: (BuildContext context) => StartCallPage(),
|
|
// ));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// notifyListeners();
|
|
// }
|
|
// }
|
|
//
|
|
// Future<void> onOfferAsync(List<Object?>? params) async {
|
|
// dynamic items = params!.toList();
|
|
// var data = jsonDecode(items.toString());
|
|
// if (isIncomingCall) {
|
|
// _pc!.setRemoteDescription(RTCSessionDescription(data[0]["sdp"]["sdp"], data[0]["sdp"]["type"]));
|
|
// RTCSessionDescription description = await _createAnswer();
|
|
// await _pc!.setLocalDescription(description);
|
|
// 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 {
|
|
// // RTCSessionDescription description = await _createAnswer();
|
|
// // await _pc.setLocalDescription(description);
|
|
// // var payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()};
|
|
// // invoke(invokeMethod: "AnswerOffer", currentUserID: outGoingCallData.callerId!, targetUserID: items[0]["id"], data: jsonEncode(payload));
|
|
// // }
|
|
// notifyListeners();
|
|
// }
|
|
|
|
//////////////////////////// OutGoing Call End ///////////////////////////////////////
|
|
|
|
// Future<bool> endCall({bool? isUserOnline}) async {
|
|
// if (isIncomingCall) {
|
|
// print("-----------------------Endeddddd By Me---------------------------");
|
|
// 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);
|
|
// }
|
|
// isCallStarted = false;
|
|
// isVideoCall = false;
|
|
// isCamOff = false;
|
|
// isMicOff = false;
|
|
// isLoudSpeaker = false;
|
|
// isIncomingCall = false;
|
|
// isOutGoingCall = false;
|
|
// isAudioCall = false;
|
|
//
|
|
// if (isCallConnected) {
|
|
// if (_pc!.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
|
|
// if (kDebugMode) {
|
|
// print("------------------ PC Stopped ----------------------------");
|
|
// }
|
|
// _pc!.close();
|
|
// _pc!.dispose();
|
|
// }
|
|
// }
|
|
// if (remoteRenderer != null) {
|
|
// remoteRenderer!.dispose();
|
|
// remoteRenderer = null;
|
|
// }
|
|
// if (localVideoRenderer != null) {
|
|
// localVideoRenderer!.dispose();
|
|
// localVideoRenderer = null;
|
|
// }
|
|
//
|
|
// if (_localStream != null) {
|
|
// _localStream!.dispose();
|
|
// _localStream = null;
|
|
// }
|
|
// if (chatHubConnection != null && !isUserOnline!) {
|
|
// chatHubConnection!.stop();
|
|
// }
|
|
// await FlutterCallkitIncoming.endAllCalls();
|
|
// 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: 1);
|
|
// } else if (isIncomingCall) {
|
|
// await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData!.targetUserId!, userStatus: 1);
|
|
// }
|
|
// isCallStarted = false;
|
|
// isVideoCall = false;
|
|
// isCamOff = false;
|
|
// isMicOff = false;
|
|
// isLoudSpeaker = false;
|
|
// if (isCallConnected) {
|
|
// if (_pc!.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
|
|
// _pc!.close();
|
|
// _pc!.dispose();
|
|
// }
|
|
// }
|
|
// if (remoteRenderer != null) {
|
|
// remoteRenderer!.dispose();
|
|
// remoteRenderer = null;
|
|
// }
|
|
// if (localVideoRenderer != null) {
|
|
// localVideoRenderer!.dispose();
|
|
// localVideoRenderer = null;
|
|
// }
|
|
//
|
|
// if (_localStream != null) {
|
|
// _localStream!.dispose();
|
|
// _localStream = null;
|
|
// }
|
|
// isOutGoingCall = false;
|
|
// isIncomingCall = false;
|
|
// isAudioCall = false;
|
|
// return true;
|
|
// }
|
|
// }
|
|
|
|
// Incoming Listeners
|
|
|
|
// void onAnswerOffer(List<Object?>? payload) async {
|
|
// // if (isIncomingCall) {
|
|
// // // print("--------------------- On Answer Offer Async ---------------------------------------");
|
|
// // //await invoke(invokeMethod: "InvokeMobile", currentUserID: AppState().getchatUserDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, debugData: {"On Answer Offer Async"});
|
|
// // } else {
|
|
// var items = payload!.toList();
|
|
// if (kDebugMode) {
|
|
// print("res: " + items.toString());
|
|
// }
|
|
// CallSessionPayLoad data = CallSessionPayLoad.fromJson(jsonDecode(items.first.toString()));
|
|
// RTCSessionDescription description = RTCSessionDescription(data.sdp!.sdp, 'answer');
|
|
// _pc!.setRemoteDescription(description);
|
|
// // }
|
|
// }
|
|
|
|
// void onHangUpAsync(List<Object?>? params) {
|
|
// print("--------------------- onHangUp ASYNC ---------------------------------");
|
|
//
|
|
// dynamic items = params!.toList();
|
|
// // if (kDebugMode) {
|
|
// // logger.i("res: " + items.toString());
|
|
// // }
|
|
// if (items[0]["id"] != AppState().chatDetails!.response!.id!) {
|
|
// if (kDebugMode) {
|
|
// print("Call Ended By Other User");
|
|
// }
|
|
// if (isIncomingCall) {
|
|
// endCall(isUserOnline: isUserOnline).then((bool value) {
|
|
// if (isCallConnected && isUserOnline) {
|
|
// isCallConnected = false;
|
|
// if (!AppState().isLogged) {
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).pop();
|
|
// } else {
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).popUntil(ModalRoute.withName(HOME));
|
|
// }
|
|
// } else {
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).pop();
|
|
// }
|
|
// });
|
|
// } else {
|
|
// if (isOutGoingCall) {
|
|
// endCall(isUserOnline: isUserOnline).then((bool value) {
|
|
// if (isCallConnected && isUserOnline) {
|
|
// isCallConnected = false;
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).popUntil(ModalRoute.withName(HOME));
|
|
// } else {
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).pop();
|
|
// }
|
|
// });
|
|
// }
|
|
// }
|
|
// } else {
|
|
// if (kDebugMode) {
|
|
// print("Call Ended By Me");
|
|
// }
|
|
// if (isOutGoingCall) {
|
|
// if (isCallConnected && isUserOnline) {
|
|
// isCallConnected = false;
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).popUntil(ModalRoute.withName(HOME));
|
|
// } else {
|
|
// Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).pop();
|
|
// }
|
|
// }
|
|
// }
|
|
// // endCall(isUserOnline: isUserOnline).then((bool value) {
|
|
// // if (isCallConnected && isUserOnline) {
|
|
// // 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");
|
|
// // }
|
|
// // if (AppState().isBackgroundCall) {
|
|
// // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
|
|
// // // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.login));
|
|
// // } else {
|
|
// // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chat));
|
|
// // }
|
|
// // }
|
|
// // if (AppState().isBackgroundCall) {
|
|
// // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
|
|
// // }
|
|
// //
|
|
// notifyListeners();
|
|
// isCallEnded = true;
|
|
// // });
|
|
// }
|
|
|
|
// Future<void> OnIncomingCallAsync(List<Object?>? params) async {
|
|
// print("--------------------- On Incoming Call ---------------------------------------");
|
|
// dynamic items = params!.toList();
|
|
// logger.d(items);
|
|
// // Map<String, dynamic> 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<String, dynamic> 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<Object> params) {
|
|
print("================= On Declained ========================");
|
|
print(params);
|
|
// endCall().then((bool value) {
|
|
// if (value) {
|
|
// isCallEnded = true;
|
|
// notifyListeners();
|
|
// }
|
|
// });
|
|
// if (params != null) {
|
|
// endCall(isUserOnline: isUserOnline).then((bool value) {
|
|
// if (isCallConnected) {
|
|
// // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
|
|
// isCallConnected = false;
|
|
// }
|
|
// isCallEnded = true;
|
|
// });
|
|
// }
|
|
}
|
|
|
|
//// Invoke Methods
|
|
|
|
// Future<void> invoke({required String invokeMethod, required int currentUserID, required int targetUserID, var data, int userStatus = 1, var debugData}) async {
|
|
// List<Object> args = [];
|
|
// if (invokeMethod == "CallUserAsync") {
|
|
// args = [currentUserID, targetUserID, isVideoCall];
|
|
// } else if (invokeMethod == "answerCallAsync") {
|
|
// args = [currentUserID, targetUserID];
|
|
// } else if (invokeMethod == "IceCandidateAsync") {
|
|
// args = [targetUserID, data];
|
|
// } else if (invokeMethod == "OfferAsync") {
|
|
// args = [targetUserID, data];
|
|
// } else if (invokeMethod == "AnswerOfferAsync") {
|
|
// args = [targetUserID, data];
|
|
// // json In Data
|
|
// } else if (invokeMethod == "UpdateUserStatusAsync") {
|
|
// args = [currentUserID, userStatus];
|
|
// } else if (invokeMethod == "HangUpAsync") {
|
|
// args = [currentUserID, targetUserID];
|
|
// } else if (invokeMethod == "InvokeMobile") {
|
|
// args = [debugData];
|
|
// }
|
|
// try {
|
|
// await chatHubConnection!.invoke("$invokeMethod", args: args);
|
|
// } catch (e) {
|
|
// print(e);
|
|
// }
|
|
// }
|
|
|
|
void stopListeners() async {
|
|
chatHubConnection!.off('OnCallDeclinedAsync');
|
|
chatHubConnection!.off('OnCallAcceptedAsync');
|
|
chatHubConnection!.off('OnIceCandidateAsync');
|
|
chatHubConnection!.off('OnAnswerOffer');
|
|
}
|
|
|
|
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<RTCPeerConnection> creatOfferWithCon() async {
|
|
// Map<String, dynamic> configuration = {
|
|
// "sdpSemantics": "plan-b",
|
|
// 'iceServers': [
|
|
// {
|
|
// 'urls': 'stun:15.185.116.59:3478',
|
|
// },
|
|
// {
|
|
// 'urls': 'turn:15.185.116.59:3479',
|
|
// 'username': 'admin',
|
|
// 'credential': 'admin',
|
|
// },
|
|
// ]
|
|
// };
|
|
// Map<String, dynamic> offerSdpConstraints = {
|
|
// 'mandatory': {
|
|
// 'OfferToReceiveAudio': true,
|
|
// 'OfferToReceiveVideo': true,
|
|
// },
|
|
// 'optional': []
|
|
// };
|
|
// RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints);
|
|
// // 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 {
|
|
// if (isIncomingCall) {
|
|
// if (e.candidate != null) {
|
|
// var payload = {"target": incomingCallData!.targetUserId, "candidate": e.toMap()};
|
|
// invoke(invokeMethod: "IceCandidateAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData!.targetUserId!, data: jsonEncode(payload));
|
|
// notifyListeners();
|
|
// }
|
|
// } else {
|
|
// if (e.candidate != null) {
|
|
// var payload = {"target": outGoingCallData!.callerId, "candidate": e.toMap()};
|
|
// invoke(invokeMethod: "IceCandidateAsync", currentUserID: outGoingCallData!.callerId!, targetUserID: outGoingCallData!.receiverId!, data: jsonEncode(payload));
|
|
// }
|
|
// }
|
|
// };
|
|
// // pc!.onTrack = (RTCTrackEvent event) async {
|
|
// //
|
|
// // String streamId = const Uuid().toString();
|
|
// // MediaStream remoteStream = await createLocalMediaStream(streamId);
|
|
// // event.streams[0].getTracks().forEach((MediaStreamTrack element) {
|
|
// // logger.i("Stream Track: " + element.id.toString());
|
|
// // // remoteRenderer.srcObject = element;
|
|
// // remoteStream.addTrack(element);
|
|
// // });
|
|
// // };
|
|
// pc.onSignalingState = (RTCSignalingState state) {
|
|
// print("signaling state: " + state.name);
|
|
// // invoke(
|
|
// // invokeMethod: "InvokeMobile",
|
|
// // currentUserID: AppState().getchatUserDetails!.response!.id!,
|
|
// // targetUserID: incomingCallData.targetUserId!,
|
|
// // debugData: {"location": "Signaling", "parms": state.name});
|
|
// };
|
|
// pc.onIceGatheringState = (RTCIceGatheringState state) {
|
|
// print("rtc ice gathering state: " + state.name);
|
|
// };
|
|
// pc.onIceConnectionState = (RTCIceConnectionState state) {
|
|
// if (RTCIceConnectionState.RTCIceConnectionStateFailed == state ||
|
|
// RTCIceConnectionState.RTCIceConnectionStateDisconnected == state ||
|
|
// RTCIceConnectionState.RTCIceConnectionStateClosed == state) {
|
|
// print("Ice Connection State:" + state.name);
|
|
//
|
|
// // endCall().then((value) {
|
|
// // notifyListeners();
|
|
// // });
|
|
// }
|
|
// };
|
|
// // pc!.onRenegotiationNeeded = _onRenegotiate;
|
|
// return pc;
|
|
// }
|
|
|
|
// void _onRenegotiate() async {
|
|
// try {
|
|
// print('onRenegotiationNeeded start');
|
|
// // makingOffer = true;
|
|
// await _pc.setLocalDescription(await _pc.createOffer(videoConstraints));
|
|
// print('onRenegotiationNeeded state after setLocalDescription: ' + _pc.signalingState.toString());
|
|
// // send offer via callManager
|
|
// var localDesc = await _pc.getLocalDescription();
|
|
// // callManager.sendCallMessage(MsgType.rtc_offer, RtcOfferAnswer(localDesc.sdp, localDesc.type));
|
|
// print('onRenegotiationNeeded; offer sent');
|
|
// } catch (e) {
|
|
// print("onRenegotiationNeeded error: " + e.toString());
|
|
// } finally {
|
|
// // makingOffer = false;
|
|
// print('onRenegotiationNeeded done');
|
|
// }
|
|
// }
|
|
|
|
// Future<RTCSessionDescription> _createOffer() async {
|
|
// RTCSessionDescription description = await _pc!.createOffer();
|
|
// // _offer = true;
|
|
// return description;
|
|
// }
|
|
//
|
|
// Future<RTCSessionDescription> _createAnswer() async {
|
|
// RTCSessionDescription description = await _pc!.createAnswer();
|
|
// // _offer = false;
|
|
// return description;
|
|
// }
|
|
|
|
//////////////////// Web RTC End Offers ////////////////////
|
|
|
|
//////////////////// CallPage Buttons //////////////////////
|
|
|
|
void micOff() {
|
|
isMicOff = !isMicOff;
|
|
_localStream!.getAudioTracks().forEach((track) {
|
|
track.enabled = !track.enabled;
|
|
});
|
|
notifyListeners();
|
|
}
|
|
|
|
void camOff() {
|
|
isCamOff = !isCamOff;
|
|
_localStream!.getVideoTracks().forEach((track) {
|
|
track.enabled = !track.enabled;
|
|
});
|
|
// if (isCamOff) {
|
|
// isVideoCall = false;
|
|
// } else {
|
|
// isVideoCall = true;
|
|
// }
|
|
notifyListeners();
|
|
}
|
|
|
|
void loudOn() {
|
|
isLoudSpeaker = !isLoudSpeaker;
|
|
remoteRenderer!.srcObject?.getAudioTracks().forEach((track) {
|
|
if (isLoudSpeaker) {
|
|
track.enableSpeakerphone(true);
|
|
} else {
|
|
track.enableSpeakerphone(false);
|
|
}
|
|
});
|
|
notifyListeners();
|
|
}
|
|
|
|
void switchCamera() {
|
|
isFrontCamera = !isFrontCamera;
|
|
Helper.switchCamera(_localStream!.getVideoTracks()[0]);
|
|
notifyListeners();
|
|
}
|
|
|
|
///////////////// Incoming Call ///////////////////////////////
|
|
|
|
Future<void> initStreams() async {
|
|
List<MediaDeviceInfo> devices = await navigator.mediaDevices.enumerateDevices();
|
|
remoteRenderer = RTCVideoRenderer();
|
|
localVideoRenderer ??= RTCVideoRenderer();
|
|
await localVideoRenderer!.initialize();
|
|
try {
|
|
_localStream = await navigator.mediaDevices.getUserMedia({
|
|
'audio': true,
|
|
'video': {
|
|
'mandatory': {
|
|
'minWidth': '640', // Provide your own width, height and frame rate here
|
|
'minHeight': '480',
|
|
'minFrameRate': '25',
|
|
},
|
|
'facingMode': 'user',
|
|
'optional': [],
|
|
"audio": true,
|
|
}
|
|
});
|
|
_localStream!.getAudioTracks().first.enableSpeakerphone(true);
|
|
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");
|
|
}
|
|
await remoteRenderer!.initialize();
|
|
notifyListeners();
|
|
}
|
|
|
|
// Future<void> startIncomingCallViaKit({bool isVCall = true, var inCallData}) async {
|
|
// AppSharedPrefs().setStringFromPrefs("isIncomingCall", "false");
|
|
// if (isVCall) {
|
|
// isVideoCall = isVCall;
|
|
// } else {
|
|
// isAudioCall = true;
|
|
// }
|
|
// await initStreams();
|
|
// isIncomingCall = true;
|
|
// incomingCallData = SingleUserChatModel.fromJson(inCallData);
|
|
// loudOn();
|
|
// // notifyListeners();
|
|
// }
|
|
|
|
// void connectIncomingCall() {
|
|
// invoke(invokeMethod: "answerCallAsync", currentUserID: AppState().getchatUserDetails.response!.id!, targetUserID: incomingCallData!.targetUserId!);
|
|
// isIncomingCallLoader = false;
|
|
// isIncomingCall = true;
|
|
// // isVideoCall = true;
|
|
//
|
|
// notifyListeners();
|
|
// }
|
|
|
|
// 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();
|
|
// }
|
|
|
|
// WebRtc
|
|
|
|
final transportProtLogger = Logger("SignalR - transport");
|
|
late Logger _logger;
|
|
|
|
RTCPeerConnection? pCon;
|
|
String? _doctorID;
|
|
String? _patientID;
|
|
|
|
String? get doctorID => _doctorID;
|
|
|
|
set doctorID(String? value) {
|
|
_doctorID = value;
|
|
}
|
|
|
|
String? get patientID => _patientID;
|
|
|
|
set patientID(String? value) {
|
|
_patientID = value;
|
|
}
|
|
|
|
bool _isAccepted = false;
|
|
|
|
bool get isAccepted => _isAccepted;
|
|
|
|
set isAccepted(bool value) {
|
|
_isAccepted = value;
|
|
}
|
|
|
|
// int _secondsRemaining = 30;
|
|
// late Timer _timer;
|
|
|
|
// void startCountTimer() {
|
|
// _timer = Timer.periodic(Duration(seconds: 1), (timer) async {
|
|
// if (_secondsRemaining > 0) {
|
|
// _secondsRemaining--;
|
|
// if (isAccepted) {
|
|
// _timer.cancel(); // Stop the timer if isAccepted becomes true
|
|
// }
|
|
// } else {
|
|
// _timer.cancel();
|
|
// if (chatHubConnection != null) {
|
|
// chatHubConnection!.stop();
|
|
// chatHubConnection = null;
|
|
// }
|
|
// chatHubConnection = await createHub();
|
|
// NoAnswer();
|
|
// }
|
|
// });
|
|
// // notifyListeners();
|
|
// }
|
|
|
|
NoAnswer() {
|
|
handleCallComplete([{}]);
|
|
}
|
|
|
|
void httpCallback(Client httpClient) {
|
|
HttpOverrides.global = HttpOverrideCertificateVerificationInDev();
|
|
}
|
|
|
|
Future<HubConnection> createHub() async {
|
|
doctorID = incomingCallData!.sessionId!.split("**").last;
|
|
String path = incomingCallData!.sessionId!.split("**").first;
|
|
patientID = incomingCallData!.receiverID;
|
|
_logger = Logger("ChatPageViewModel");
|
|
final httpConnectionOptions = HttpConnectionOptions(logMessageContent: true, httpClient: WebSupportingHttpClient(_logger, httpClientCreateCallback: httpCallback));
|
|
var urlWithParams = path + "UserID=$patientID&ProjectId=15&IsAdmin=false&To=$doctorID";
|
|
HubConnection hubCon =
|
|
await HubConnectionBuilder().withUrl(urlWithParams, options: httpConnectionOptions).withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).configureLogging(_logger).build();
|
|
return hubCon;
|
|
}
|
|
|
|
Future<void> initCall({required bool isConnectCall}) async {
|
|
if (chatHubConnection != null) {
|
|
chatHubConnection!.stop();
|
|
chatHubConnection = null;
|
|
}
|
|
chatHubConnection = await createHub();
|
|
if (doctorID != null) {
|
|
try {
|
|
chatHubConnection!.onclose(({error}) {
|
|
Utils.showErrorToast(error.toString());
|
|
});
|
|
register();
|
|
if (chatHubConnection!.state == HubConnectionState.Disconnected) {
|
|
await chatHubConnection!.start();
|
|
}
|
|
if (chatHubConnection!.state == HubConnectionState.Connected) {
|
|
if (chatHubConnection != null) {
|
|
patientID = chatHubConnection!.connectionId;
|
|
print("DOC: " + doctorID.toString());
|
|
print("PAT " + patientID.toString());
|
|
try {
|
|
isConnectCall ? ping("Call_Accept") : ping("Call_Decline");
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print(e.toString());
|
|
Utils.showErrorToast(e.toString());
|
|
}
|
|
} else {
|
|
Utils.showErrorToast("Doctor ID is not correct");
|
|
}
|
|
}
|
|
|
|
ping(String eventName) async {
|
|
print("============ $eventName =====================");
|
|
if (chatHubConnection != null) if (chatHubConnection!.state == HubConnectionState.Connected) {
|
|
print("============ CONNECTED ==============");
|
|
dynamic payload = {"UserID": int.parse(incomingCallData!.receiverID!)};
|
|
if (eventName == "Call_Complete") payload = {"from": patientID, "to": doctorID};
|
|
await chatHubConnection!.invoke(eventName, args: [payload]).onError((error, stackTrace) {}).whenComplete(() {
|
|
if (eventName == "Call_Decline" || eventName == "Call_Complete" || eventName == "Call_NoAnswer") {
|
|
if (chatHubConnection != null) {
|
|
chatHubConnection!.stop();
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
print("============ ELSE RECONNECT ==============");
|
|
chatHubConnection = await createHub();
|
|
chatHubConnection!.start();
|
|
ping(eventName);
|
|
}
|
|
}
|
|
|
|
void register() async {
|
|
chatHubConnection!.on("pre_offer", handlePreOffer);
|
|
chatHubConnection!.on("on_offer", handleOnOffer);
|
|
chatHubConnection!.on("on_ice_candidate", handleIceCandidate);
|
|
// New Events
|
|
chatHubConnection!.on("Call_Decline", handleCallDecline);
|
|
chatHubConnection!.on("call_completed", handleCallComplete);
|
|
if (kDebugMode) debugPrint("Listners Initiated");
|
|
}
|
|
|
|
// genericCheckEvent(List<Object?>? params) async {
|
|
// print("------------- Generic Event Triggered ---------------");
|
|
// print("------------- Generic Event Triggered ---------------");
|
|
// print(params);
|
|
// print("------------- Generic Event Triggered ---------------");
|
|
// print("------------- Generic Event Triggered ---------------");
|
|
// }
|
|
|
|
handlePreOffer(List<Object?>? params) async {
|
|
print("----------Event Pre Offer Received ----------");
|
|
dynamic items = params!.toList();
|
|
if (kDebugMode) {
|
|
print("Doctor ID : " + items[0]['from'].toString());
|
|
print("Patient ID: " + items[0]['to'].toString());
|
|
}
|
|
doctorID = items[0]['from'];
|
|
patientID = items[0]['to'];
|
|
initStreams();
|
|
createPConnection();
|
|
sendPreAnswerOffer();
|
|
}
|
|
|
|
handleOnOffer(List<Object?>? params) async {
|
|
print("----------Event On Offer Received ----------");
|
|
dynamic items = params!.toList();
|
|
var data = jsonDecode(items[0]["offer"]);
|
|
_localStream?.getTracks().forEach((track) {
|
|
pCon!.addTrack(track, _localStream!);
|
|
});
|
|
await pCon!.setRemoteDescription(RTCSessionDescription(data["sdp"], data["type"]));
|
|
RTCSessionDescription description = await pCon!.createAnswer();
|
|
await pCon!.setLocalDescription(description);
|
|
var payload = {
|
|
"to": doctorID,
|
|
"callerSocketId": patientID,
|
|
"answer": "${json.encode(description.toMap())}",
|
|
};
|
|
if (chatHubConnection!.state == HubConnectionState.Connected) {
|
|
print("---------Answer Offer Invoke --------");
|
|
await chatHubConnection!.invoke("OnAnswerOffer", args: [payload]).onError((error, stackTrace) {
|
|
print("error sending offer answer");
|
|
Utils.showErrorToast(error.toString());
|
|
});
|
|
}
|
|
startCallByRTC();
|
|
Future.delayed(Duration(seconds: 2), () {
|
|
Navigator.pushReplacement(
|
|
locator<NavigationService>().navigatorKey.currentContext!,
|
|
MaterialPageRoute(
|
|
builder: (BuildContext context) => StartCallPage(),
|
|
));
|
|
});
|
|
}
|
|
|
|
handleIceCandidate(List<Object?>? params) async {
|
|
print("----------Event Ice Candidate Received ----------");
|
|
dynamic items = params!.toList();
|
|
var val = jsonDecode(items[0]["candidate"]);
|
|
RemoteIceCandidatePayLoad data = await RemoteIceCandidatePayLoad(
|
|
target: 00000, candidate: Candidate(candidate: val["candidate"], sdpMid: val["sdpMid"], sdpMLineIndex: val["sdpMLineIndex"], usernameFragment: val["usernameFragment"]));
|
|
if (pCon != null) {
|
|
pCon!.addCandidate(RTCIceCandidate(data.candidate!.candidate, data.candidate!.sdpMid, data.candidate!.sdpMLineIndex));
|
|
}
|
|
}
|
|
|
|
handleCallDecline(List<Object?>? params) {
|
|
print("----------handle Call Decline Received ----------");
|
|
dynamic items = params!.toList();
|
|
debuglogger.d(items);
|
|
}
|
|
|
|
handleCallComplete(List<Object?>? params) {
|
|
print("----------handle Call Complete Received ----------");
|
|
dynamic items = params!.toList();
|
|
debuglogger.d(items);
|
|
if (isCallConnected) ping("Call_Complete");
|
|
if (!isCallConnected && !isAccepted) {
|
|
ping("Call_NoAnswer");
|
|
} else {
|
|
if (!isCallConnected) ping("Call_Decline");
|
|
}
|
|
isCallConnected = false;
|
|
isCallStarted = false;
|
|
isVideoCall = false;
|
|
isCamOff = false;
|
|
isMicOff = false;
|
|
isLoudSpeaker = false;
|
|
isIncomingCall = false;
|
|
isOutGoingCall = false;
|
|
isAudioCall = false;
|
|
isAccepted = false;
|
|
if (pCon != null) if (pCon!.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
|
|
if (_localStream != null) pCon!.removeStream(_localStream!);
|
|
pCon!.close();
|
|
pCon!.dispose();
|
|
}
|
|
|
|
if (remoteRenderer != null) {
|
|
remoteRenderer!.dispose();
|
|
remoteRenderer = null;
|
|
}
|
|
if (localVideoRenderer != null) {
|
|
localVideoRenderer!.dispose();
|
|
localVideoRenderer = null;
|
|
}
|
|
|
|
if (_localStream != null) {
|
|
_localStream!.dispose();
|
|
_localStream = null;
|
|
}
|
|
|
|
// if (chatHubConnection != null && !isUserOnline) {
|
|
// chatHubConnection!.stop();
|
|
// }
|
|
Navigator.of(locator<NavigationService>().navigatorKey.currentContext!).popAndPushNamed(HOME);
|
|
}
|
|
|
|
void createPConnection() async {
|
|
Map<String, dynamic> configuration = {
|
|
"sdpSemantics": "plan-b",
|
|
'iceServers': [
|
|
{
|
|
'urls': 'stun:15.185.116.59:3478',
|
|
},
|
|
{
|
|
'urls': 'turn:15.185.116.59:3479',
|
|
'username': 'admin',
|
|
'credential': 'admin',
|
|
}
|
|
],
|
|
"iceCandidatePoolSize": 10
|
|
};
|
|
Map<String, dynamic> offerSdpConstraints = {
|
|
'mandatory': {
|
|
'OfferToReceiveAudio': true,
|
|
'OfferToReceiveVideo': true,
|
|
},
|
|
'optional': []
|
|
};
|
|
pCon = await createPeerConnection(configuration, offerSdpConstraints);
|
|
|
|
pCon!.onConnectionState = (RTCPeerConnectionState state) {};
|
|
pCon!.onAddStream = (MediaStream stream) {
|
|
remoteRenderer!.srcObject = stream;
|
|
notifyListeners();
|
|
};
|
|
|
|
pCon!.onIceCandidate = (RTCIceCandidate e) async {
|
|
if (e.candidate != null) {
|
|
await pCon!.addCandidate(e);
|
|
var data = {"target": doctorID, "callerSocketId": doctorID, "from": patientID, "calleePersonalCode": patientID, "to": doctorID, "candidate": "${json.encode(e.toMap())}"};
|
|
if (chatHubConnection!.state == HubConnectionState.Connected) {
|
|
await chatHubConnection!.invoke('IceCandidate', args: [data]).onError((error, stackTrace) {
|
|
Utils.showErrorToast(error.toString());
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
pCon!.onSignalingState = (RTCSignalingState state) {
|
|
print("signaling state: " + state.name);
|
|
};
|
|
pCon!.onIceGatheringState = (RTCIceGatheringState state) {
|
|
print("rtc ice gathering state: " + state.name);
|
|
};
|
|
pCon!.onIceConnectionState = (RTCIceConnectionState state) {
|
|
if (RTCIceConnectionState.RTCIceConnectionStateFailed == state ||
|
|
RTCIceConnectionState.RTCIceConnectionStateDisconnected == state ||
|
|
RTCIceConnectionState.RTCIceConnectionStateClosed == state) {
|
|
print("Ice Connection State:" + state.name);
|
|
}
|
|
};
|
|
}
|
|
|
|
sendPreAnswerOffer() async {
|
|
var data = {
|
|
"to": doctorID,
|
|
"calleePersonalCode": patientID,
|
|
"preOfferAnswer": "",
|
|
};
|
|
print(data);
|
|
if (chatHubConnection!.state == HubConnectionState.Connected) {
|
|
await chatHubConnection!.invoke("SendPreOfferAnswer", args: [data]).onError((error, stackTrace) {
|
|
print("error sending pre offer answer");
|
|
Utils.showErrorToast(error.toString());
|
|
});
|
|
}
|
|
}
|
|
|
|
startCallByRTC() {
|
|
isVideoCall = true;
|
|
isIncomingCallLoader = false;
|
|
isIncomingCall = true;
|
|
isCallConnected = true;
|
|
}
|
|
}
|
|
|
|
class HttpOverrideCertificateVerificationInDev extends HttpOverrides {
|
|
@override
|
|
HttpClient createHttpClient(SecurityContext? context) {
|
|
return super.createHttpClient(context)..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
|
|
}
|
|
}
|
|
|
|
// class ChatService extends BaseService {
|
|
// Future<getUserToken.UserAutoLoginModel> getUserCallToken({required String userid}) async {
|
|
// getUserToken.UserAutoLoginModel userLoginResponse = getUserToken.UserAutoLoginModel();
|
|
// http.post(Uri.parse("${ApiConsts.chatLoginTokenUrl}externaluserlogin"), body: {
|
|
// "employeeNumber": userid,
|
|
// "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
|
|
// }).then((response) {
|
|
// userLoginResponse = getUserToken.userAutoLoginModelFromJson(response.body);
|
|
// }).onError((error, stackTrace) {
|
|
// hasError = true;
|
|
// print(error);
|
|
// super.error = error.toString();
|
|
// });
|
|
//
|
|
// return userLoginResponse;
|
|
// }
|
|
// }
|