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.
		
		
		
		
		
			
		
			
	
	
		
			822 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Dart
		
	
		
		
			
		
	
	
			822 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Dart
		
	
| 
								 
											2 years ago
										 
									 | 
							
								import 'dart:convert';
							 | 
						||
| 
								 | 
							
								import 'dart:io';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/core/service/NavigationService.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/locator.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/routes.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/utils/utils.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/app_state.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/call/chat_incoming_call_screen.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/consts.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/model/call.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/model/get_single_user_chat_call.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/model/get_user_login_token.dart';
							 | 
						||
| 
								 | 
							
								import 'package:doctor_app_flutter/voipcall/model/webrtc_payloads.dart';
							 | 
						||
| 
								 | 
							
								import 'package:flutter/foundation.dart';
							 | 
						||
| 
								 | 
							
								import 'package:flutter/material.dart';
							 | 
						||
| 
								 | 
							
								import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
							 | 
						||
| 
								 | 
							
								import 'package:flutter_webrtc/flutter_webrtc.dart';
							 | 
						||
| 
								 | 
							
								import 'package:http/http.dart' as http;
							 | 
						||
| 
								 | 
							
								import 'package:just_audio/just_audio.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 = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<void> buildHubConnection() async {
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      chatHubConnection = await getHubConnection();
							 | 
						||
| 
								 | 
							
								      await chatHubConnection!.start();
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      print(e.toString());
							 | 
						||
| 
								 | 
							
								      Utils.showErrorToast(e.toString());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (kDebugMode) {
							 | 
						||
| 
								 | 
							
								      print("Hub Conn: Startedddddddd");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    registerCallListners();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//{"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 = UserAutoLoginModel(
							 | 
						||
| 
								 | 
							
								      response: Response.fromJson({
							 | 
						||
| 
								 | 
							
								        "id": 266642,
							 | 
						||
| 
								 | 
							
								        "userName": "Muhamad.Alam",
							 | 
						||
| 
								 | 
							
								        "email": "Muhamad.Alam@cloudsolutions.com.sa",
							 | 
						||
| 
								 | 
							
								        "phone": null,
							 | 
						||
| 
								 | 
							
								        "title": "Muhamad.Alam",
							 | 
						||
| 
								 | 
							
								        "token":
							 | 
						||
| 
								 | 
							
								            "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIyNjY2NDIiLCJlbWFpbCI6Ik11aGFtYWQuQWxhbUBjbG91ZHNvbHV0aW9ucy5jb20uc2EiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3VzZXJkYXRhIjoiTXVoYW1hZC5BbGFtIiwibmJmIjoxNzA4MjU2MjU4LCJleHAiOjE3MDgzNDI2NTgsImlhdCI6MTcwODI1NjI1OH0.Ol8VJFhaFMFgcMXpFi8XI38v8dDmh8-tpPaXSWTXQF1yXqPFNtnyN2t_6ar3-N92bS60yZ1w3v4s3Tx7dirfow",
							 | 
						||
| 
								 | 
							
								        "isDomainUser": true,
							 | 
						||
| 
								 | 
							
								        "isActiveCode": false,
							 | 
						||
| 
								 | 
							
								        "encryptedUserId": "8NOEvvO7oi0=",
							 | 
						||
| 
								 | 
							
								        "encryptedUserName": "YaYBnsXyEusQT8TAOmYQqA=="
							 | 
						||
| 
								 | 
							
								      }),
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    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();
							 | 
						||
| 
								 | 
							
								    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':
							 | 
						||
| 
								 | 
							
								            //isVideoCall?
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								          'mandatory': {
							 | 
						||
| 
								 | 
							
								            'minWidth': '640', // Provide your own width, height and frame rate here
							 | 
						||
| 
								 | 
							
								            'minHeight': '480',
							 | 
						||
| 
								 | 
							
								            'minFrameRate': '30',
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          'facingMode': 'user',
							 | 
						||
| 
								 | 
							
								          'optional': [],
							 | 
						||
| 
								 | 
							
								          "audio": true,
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // : false
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      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");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // localVideoRenderer.srcObject = _localStream;
							 | 
						||
| 
								 | 
							
								    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();
							 | 
						||
| 
								 | 
							
								// }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ChatService {
							 | 
						||
| 
								 | 
							
								  Future<UserAutoLoginModel> getUserCallToken({required String userid}) async {
							 | 
						||
| 
								 | 
							
								    UserAutoLoginModel userLoginResponse = UserAutoLoginModel();
							 | 
						||
| 
								 | 
							
								    var headers = {'Content-Type': 'application/json'};
							 | 
						||
| 
								 | 
							
								    var request = http.Request('POST', Uri.parse("${ApiConsts.chatLoginTokenUrl}externaluserlogin"));
							 | 
						||
| 
								 | 
							
								    request.body = json.encode({"employeeNumber": "341682", "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG"});
							 | 
						||
| 
								 | 
							
								    request.headers.addAll(headers);
							 | 
						||
| 
								 | 
							
								    http.StreamedResponse response = await request.send();
							 | 
						||
| 
								 | 
							
								    if (response.statusCode == 200) {
							 | 
						||
| 
								 | 
							
								      userLoginResponse = userAutoLoginModelFromJson(await response.stream.bytesToString());
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      print(response.reasonPhrase);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return userLoginResponse;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |