From c414fd7f2039c3d30969463de3ce45a5c2a3e89e Mon Sep 17 00:00:00 2001 From: Aamir Date: Mon, 15 Apr 2024 12:00:55 +0300 Subject: [PATCH] voip call --- lib/pages/livecare/incoming_call.dart | 40 +- lib/uitl/push-notification-handler.dart | 8 +- .../call/chat_incoming_call_screen.dart | 643 ++++++------------ lib/voipcall/provider/chat_call_provider.dart | 162 +++-- 4 files changed, 329 insertions(+), 524 deletions(-) diff --git a/lib/pages/livecare/incoming_call.dart b/lib/pages/livecare/incoming_call.dart index 5b6e76ad..a402c6b7 100644 --- a/lib/pages/livecare/incoming_call.dart +++ b/lib/pages/livecare/incoming_call.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart'; import 'package:diplomaticquarterapp/pages/conference/widgets/platform_exception_alert_dialog.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; @@ -9,7 +11,6 @@ import 'package:diplomaticquarterapp/voipcall/provider/chat_call_provider.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; -import 'package:logger/logger.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; @@ -29,17 +30,16 @@ class _IncomingCallState extends State with SingleTickerProviderSt bool openCallInWeb = true; final player = AudioPlayer(); bool isCameraReady = false; - Logger mylogs = Logger(); ChatCallProvider? callProv; + bool isAccepted = false; @override void initState() { _animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 500)); isCameraReady = false; - WidgetsBinding.instance.addPostFrameCallback((_) => _runAnimation()); - //mylogs.d(widget.incomingCallData!.toJson()); super.initState(); + initCount(); } @override @@ -50,11 +50,12 @@ class _IncomingCallState extends State with SingleTickerProviderSt super.dispose(); } - acceptCall() async { + acceptCall({required bool isConnectCall}) async { Future micPer = Permission.microphone.request(); Future camPer = Permission.camera.request(); if (await micPer.isGranted && await camPer.isGranted) { - await callProv!.buildHubConnection(); + isAccepted = true; + await callProv!.initCall(isConnectCall: isConnectCall); } else if (await micPer.isDenied) { micPer = Permission.microphone.request(); } else if (await camPer.isDenied) { @@ -62,9 +63,18 @@ class _IncomingCallState extends State with SingleTickerProviderSt } } + endCall() async { + await callProv!.initCall(isConnectCall: false); + LandingPage.isOpenCallPage = false; + isAccepted = false; + player.stop(); + Navigator.of(context).pop(); + } + @override Widget build(BuildContext context) { callProv = Provider.of(context); + callProv!.incomingCallData = widget.incomingCallData; return AppScaffold( isShowAppBar: false, isShowDecPage: false, @@ -154,9 +164,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt child: Container( child: RawMaterialButton( onPressed: () { - // _submit(); - callProv!.incomingCallData = widget.incomingCallData; - acceptCall(); + acceptCall(isConnectCall: true); }, elevation: 2.0, fillColor: Colors.green, @@ -172,7 +180,8 @@ class _IncomingCallState extends State with SingleTickerProviderSt Container( child: RawMaterialButton( onPressed: () { - backToHome(); + //backToHome(); + endCall(); }, elevation: 2.0, fillColor: Colors.red, @@ -276,4 +285,15 @@ class _IncomingCallState extends State with SingleTickerProviderSt print("Error: $e"); } } + + void initCount() { + Future.delayed( + Duration(seconds: 30), + () async { + if (!isAccepted) { + callProv!.NoAnswer(); + } + }, + ); + } } diff --git a/lib/uitl/push-notification-handler.dart b/lib/uitl/push-notification-handler.dart index 8aeb83f8..0cf0e3d3 100644 --- a/lib/uitl/push-notification-handler.dart +++ b/lib/uitl/push-notification-handler.dart @@ -156,12 +156,8 @@ _incomingCall(Map data) async { LandingPage.incomingCallData = IncomingCallData.fromJson(data); if (LandingPage.isOpenCallPage == false) { LandingPage.isOpenCallPage = true; - final bool permited = await AppPermission.askVideoCallPermission(currentContext!); - if (permited) - await NavigationService.navigateToPage( - IncomingCall(incomingCallData: LandingPage.incomingCallData), - ); - + final bool permitted = await AppPermission.askVideoCallPermission(currentContext!); + if (permitted) await NavigationService.navigateToPage(IncomingCall(incomingCallData: LandingPage.incomingCallData)); LandingPage.isOpenCallPage = false; } await Future.delayed(Duration(milliseconds: 500)); diff --git a/lib/voipcall/call/chat_incoming_call_screen.dart b/lib/voipcall/call/chat_incoming_call_screen.dart index b7aa9240..b6ab7283 100644 --- a/lib/voipcall/call/chat_incoming_call_screen.dart +++ b/lib/voipcall/call/chat_incoming_call_screen.dart @@ -23,7 +23,6 @@ class StartCallPage extends StatefulWidget { class _StartCallPageState extends State { DragController dragController = DragController(); - ChatCallProvider? cProv; @override void initState() { @@ -122,17 +121,6 @@ class _StartCallPageState extends State { @override Widget build(BuildContext context) { - cProv = context.read(); - // if (!cProv!.isOutGoingCall) { - // if (Platform.isAndroid) { - // // startCall(); - // } else if (Platform.isIOS) { - // // cProv!.buildHubConnection(); - // // startIosCall(); - // // startIosCall(); - // } - // } - return Scaffold( extendBody: true, body: Consumer( @@ -143,467 +131,230 @@ class _StartCallPageState extends State { height: double.infinity, child: Center(child: CircularProgressIndicator()), ) - : prov.isIncomingCall - ? Container( - width: double.infinity, - height: double.infinity, - color: Colors.black, - child: Stack( - alignment: FractionalOffset.center, - children: [ - if (!prov.isAudioCall && prov.isVideoCall) - RTCVideoView( - prov.remoteRenderer!, - objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, - key: const Key('remote'), + : Container( + width: double.infinity, + height: double.infinity, + color: Colors.black, + child: Stack( + alignment: FractionalOffset.center, + children: [ + if (!prov.isAudioCall && prov.isVideoCall) + RTCVideoView( + prov.remoteRenderer!, + objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, + key: const Key('remote'), + ), + if (prov.isVideoCall) + DraggableWidget( + bottomMargin: 20, + topMargin: 40, + intialVisibility: true, + horizontalSpace: 20, + shadowBorderRadius: 50, + initialPosition: AnchoringPosition.topLeft, + dragController: dragController, + normalShadow: const BoxShadow(spreadRadius: 0.0, blurRadius: 0.0), + draggingShadow: const BoxShadow(spreadRadius: 0.0, blurRadius: 0.0), + child: SizedBox( + height: 200, + width: 140, + child: RTCVideoView( + prov.localVideoRenderer!, + mirror: true, + // filterQuality: FilterQuality.high, + objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), - if (prov.isVideoCall) - DraggableWidget( - bottomMargin: 20, - topMargin: 40, - intialVisibility: true, - horizontalSpace: 20, - shadowBorderRadius: 50, - initialPosition: AnchoringPosition.topLeft, - dragController: dragController, - normalShadow: const BoxShadow(spreadRadius: 0.0, blurRadius: 0.0), - draggingShadow: const BoxShadow(spreadRadius: 0.0, blurRadius: 0.0), - child: SizedBox( - height: 200, - width: 140, - child: RTCVideoView( - prov.localVideoRenderer!, - mirror: true, - // filterQuality: FilterQuality.high, - objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, + ), + ), + if (!prov.isVideoCall) + Positioned.fill( + child: ClipRect( + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0), + child: Container( + decoration: BoxDecoration( + color: MyColors.grey57Color.withOpacity( + 0.3, + ), ), - ), - ), - if (!prov.isVideoCall) - Positioned.fill( - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0), - child: Container( - decoration: BoxDecoration( - color: MyColors.grey57Color.withOpacity( - 0.3, - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + SizedBox( + height: 40, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( - height: 40, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: const EdgeInsets.all(21.0), - child: Container( - margin: const EdgeInsets.only( - left: 10.0, - right: 10.0, + Container( + margin: const EdgeInsets.all(21.0), + child: Container( + margin: const EdgeInsets.only( + left: 10.0, + right: 10.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 70, + width: 70, + fit: BoxFit.cover, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 70, - width: 70, - fit: BoxFit.cover, - ), - SizedBox( - height: 10, - ), - Text( - prov.incomingCallData!.doctorname ?? "", - style: const TextStyle( - fontSize: 21, - decoration: TextDecoration.none, - fontWeight: FontWeight.bold, - color: MyColors.white, - letterSpacing: -1.26, - height: 23 / 12, - ), - ), - const Text( - "On Call", - style: TextStyle( - fontSize: 16, - decoration: TextDecoration.none, - fontWeight: FontWeight.w600, - color: Color( - 0xffC6C6C6, - ), - letterSpacing: -0.48, - height: 23 / 24, - ), - ), - const SizedBox( - height: 2, + SizedBox( + height: 10, + ), + Text( + prov.incomingCallData!.doctorname ?? "", + style: const TextStyle( + fontSize: 21, + decoration: TextDecoration.none, + fontWeight: FontWeight.bold, + color: MyColors.white, + letterSpacing: -1.26, + height: 23 / 12, + ), + ), + const Text( + "On Call", + style: TextStyle( + fontSize: 16, + decoration: TextDecoration.none, + fontWeight: FontWeight.w600, + color: Color( + 0xffC6C6C6, ), - ], + letterSpacing: -0.48, + height: 23 / 24, + ), ), - ), + const SizedBox( + height: 2, + ), + ], ), - ], + ), ), ], ), - ), + ], ), ), ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - padding: const EdgeInsets.only( - bottom: 20, - left: 40, - right: 40, - ), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // if (provider.isVideoCall) - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.loudOn(); - }, - elevation: 2.0, - fillColor: prov.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: const Icon( - Icons.volume_up, - color: MyColors.white, - size: 30.0, - ), - ), - if (prov.isVideoCall) - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.camOff(); - }, - elevation: 2.0, - fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: Icon( - prov.isCamOff ? Icons.videocam_off : Icons.videocam, - color: MyColors.white, - size: 30.0, - ), - ), - if (prov.isVideoCall) - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.switchCamera(); - }, - elevation: 2.0, - fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: Icon( - prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, - color: MyColors.white, - size: 30.0, - ), - ), - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.micOff(); - }, - elevation: 2.0, - fillColor: prov.isMicOff ? MyColors.textMixColor : Colors.grey, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: Icon( - prov.isMicOff ? Icons.mic_off : Icons.mic, - color: MyColors.white, - size: 30.0, - ), - ), - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - // prov.endCall(isUserOnline: prov.isUserOnline).then((bool value) { - // if (value) { - // Navigator.of(context).pop(); - // } - // }); - }, - elevation: 2.0, - fillColor: MyColors.redA3Color, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: const Icon( - Icons.call_end, - color: MyColors.white, - size: 30.0, - ), - ), - ], - ), - ), ), - ], - ), - ) - : prov.isOutGoingCall - ? Container( - width: double.infinity, - height: double.infinity, - color: Colors.black, - child: Stack( - alignment: FractionalOffset.center, + ), + Align( + alignment: Alignment.bottomCenter, + child: Container( + padding: const EdgeInsets.only( + bottom: 20, + left: 40, + right: 40, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (!prov.isAudioCall && prov.isVideoCall) - RTCVideoView( - prov.remoteRenderer!, - objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, - key: const Key('remote'), + // if (provider.isVideoCall) + RawMaterialButton( + constraints: const BoxConstraints(), + onPressed: () { + prov.loudOn(); + }, + elevation: 2.0, + fillColor: prov.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, + padding: const EdgeInsets.all( + 10.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.volume_up, + color: MyColors.white, + size: 30.0, ), + ), if (prov.isVideoCall) - DraggableWidget( - bottomMargin: 20, - topMargin: 40, - intialVisibility: true, - horizontalSpace: 20, - shadowBorderRadius: 50, - initialPosition: AnchoringPosition.topLeft, - dragController: dragController, - normalShadow: const BoxShadow(spreadRadius: 0.0, blurRadius: 0.0), - draggingShadow: const BoxShadow(spreadRadius: 0.0, blurRadius: 0.0), - child: SizedBox( - height: 200, - width: 140, - child: RTCVideoView( - prov.localVideoRenderer!, - mirror: true, - objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, - ), + RawMaterialButton( + constraints: const BoxConstraints(), + onPressed: () { + prov.camOff(); + }, + elevation: 2.0, + fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey, + padding: const EdgeInsets.all( + 10.0, ), - ), - if (!prov.isVideoCall) - Positioned.fill( - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0), - child: Container( - decoration: BoxDecoration( - color: MyColors.grey57Color.withOpacity( - 0.3, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - SizedBox( - height: 40, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: const EdgeInsets.all(21.0), - child: Container( - margin: const EdgeInsets.only( - left: 10.0, - right: 10.0, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 70, - width: 70, - fit: BoxFit.cover, - ), - SizedBox( - height: 10, - ), - Text( - prov.outGoingCallData!.receiverName!, - style: const TextStyle( - fontSize: 21, - decoration: TextDecoration.none, - fontWeight: FontWeight.bold, - color: MyColors.white, - letterSpacing: -1.26, - height: 23 / 12, - ), - ), - const Text( - "On Call", - style: TextStyle( - fontSize: 16, - decoration: TextDecoration.none, - fontWeight: FontWeight.w600, - color: Color( - 0xffC6C6C6, - ), - letterSpacing: -0.48, - height: 23 / 24, - ), - ), - const SizedBox( - height: 2, - ), - ], - ), - ), - ), - ], - ), - ], - ), - ), - ), + shape: const CircleBorder(), + child: Icon( + prov.isCamOff ? Icons.videocam_off : Icons.videocam, + color: MyColors.white, + size: 30.0, ), ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - padding: const EdgeInsets.only( - bottom: 20, - left: 40, - right: 40, + if (prov.isVideoCall) + RawMaterialButton( + constraints: const BoxConstraints(), + onPressed: () { + prov.switchCamera(); + }, + elevation: 2.0, + fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor, + padding: const EdgeInsets.all( + 10.0, ), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // if (provider.isVideoCall) - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.loudOn(); - }, - elevation: 2.0, - fillColor: prov.isLoudSpeaker ? MyColors.textMixColor : Colors.grey, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: const Icon( - Icons.volume_up, - color: MyColors.white, - size: 30.0, - ), - ), - - if (prov.isVideoCall) - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.camOff(); - }, - elevation: 2.0, - fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: Icon( - prov.isCamOff ? Icons.videocam_off : Icons.videocam, - color: MyColors.white, - size: 30.0, - ), - ), - if (prov.isVideoCall) - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.switchCamera(); - }, - elevation: 2.0, - fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: Icon( - prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, - color: MyColors.white, - size: 30.0, - ), - ), - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - prov.micOff(); - }, - elevation: 2.0, - fillColor: prov.isMicOff ? MyColors.textMixColor : Colors.grey, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: Icon( - prov.isMicOff ? Icons.mic_off : Icons.mic, - color: MyColors.white, - size: 30.0, - ), - ), - RawMaterialButton( - constraints: const BoxConstraints(), - onPressed: () { - // prov.endCall(isUserOnline: prov.isUserOnline).then( - // (bool value) { - // if (value) { - // Navigator.of(context).pop(); - // } - // }, - // ); - }, - elevation: 2.0, - fillColor: MyColors.redA3Color, - padding: const EdgeInsets.all( - 10.0, - ), - shape: const CircleBorder(), - child: const Icon( - Icons.call_end, - color: MyColors.white, - size: 30.0, - ), - ), - ], + shape: const CircleBorder(), + child: Icon( + prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera, + color: MyColors.white, + size: 30.0, ), ), + RawMaterialButton( + constraints: const BoxConstraints(), + onPressed: () { + prov.micOff(); + }, + elevation: 2.0, + fillColor: prov.isMicOff ? MyColors.textMixColor : Colors.grey, + padding: const EdgeInsets.all( + 10.0, + ), + shape: const CircleBorder(), + child: Icon( + prov.isMicOff ? Icons.mic_off : Icons.mic, + color: MyColors.white, + size: 30.0, + ), + ), + RawMaterialButton( + constraints: const BoxConstraints(), + onPressed: () { + prov.handleCallComplete([{}]); + }, + elevation: 2.0, + fillColor: MyColors.redA3Color, + padding: const EdgeInsets.all( + 10.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.call_end, + color: MyColors.white, + size: 30.0, + ), ), ], ), - ) - : const SizedBox(); + ), + ), + ], + ), + ); }, ), ); diff --git a/lib/voipcall/provider/chat_call_provider.dart b/lib/voipcall/provider/chat_call_provider.dart index d82eddac..0fb97064 100644 --- a/lib/voipcall/provider/chat_call_provider.dart +++ b/lib/voipcall/provider/chat_call_provider.dart @@ -4,6 +4,7 @@ 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'; @@ -858,56 +859,79 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { _patientID = value; } - void _httpClientCreateCallback(Client httpClient) { + 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 buildHubConnection() async { + Future createHub() async { doctorID = incomingCallData!.sessionId!.split("**").last; - // doctorID = "6wgFpttYUsdnB-klo-3xeg"; String path = incomingCallData!.sessionId!.split("**").first; patientID = incomingCallData!.receiverID; _logger = Logger("ChatPageViewModel"); - final logger = _logger; + 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 initCall({required bool isConnectCall}) async { if (chatHubConnection != null) { chatHubConnection!.stop(); chatHubConnection = null; } + chatHubConnection = await createHub(); if (doctorID != null) { try { - final httpConnectionOptions = - new HttpConnectionOptions(httpClient: WebSupportingHttpClient(logger, httpClientCreateCallback: _httpClientCreateCallback), logger: logger, logMessageContent: true); - - var urlWithParams = path + "UserID=$patientID&ProjectId=15&IsAdmin=false&To=$doctorID"; - print(urlWithParams); - chatHubConnection = - await HubConnectionBuilder().withUrl(urlWithParams, options: httpConnectionOptions).withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).configureLogging(logger).build(); - chatHubConnection!.onclose(({error}) { - // print("Connection Closed"); Utils.showErrorToast(error.toString()); }); register(); if (chatHubConnection!.state == HubConnectionState.Disconnected) { await chatHubConnection!.start(); - print(chatHubConnection!.state); } if (chatHubConnection!.state == HubConnectionState.Connected) { if (chatHubConnection != null) { patientID = chatHubConnection!.connectionId; print("DOC: " + doctorID.toString()); print("PAT " + patientID.toString()); - print("Success Chat Con ID::: " + chatHubConnection!.connectionId.toString()); try { - chatHubConnection!.invoke("Call_Accepts", args: [ - // jsonEncode({"UserID": int.parse(incomingCallData!.receiverID!)}) - {"UserID": 4767780} - ]).onError( - (error, stackTrace) => print( - error.toString(), - ), - ); + isConnectCall ? ping("Call_Accept") : ping("Call_Decline"); } catch (e) { print(e); } @@ -916,48 +940,58 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { } catch (e) { print(e.toString()); Utils.showErrorToast(e.toString()); - chatHubConnection!.invoke("Call_Accepts", args: [ - // jsonEncode({"UserID": int.parse(incomingCallData!.receiverID!)}) - {4767780} - ]).onError( - (error, stackTrace) => print( - error.toString(), - ), - ); - // await buildHubConnection(); } } else { Utils.showErrorToast("Doctor ID is not correct"); } } - invoke(String method) async {} + 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("OnOffer", handleOnOffer); - chatHubConnection!.on("IceCandidate", handleIceCandidate); + 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_NoAnswer", handleNoAnswerCall); - chatHubConnection!.on("CallCompleted", handleCallComplete); - chatHubConnection!.on("connected_users", genericCheckEvent); - print("Listners Initiated"); + chatHubConnection!.on("call_completed", handleCallComplete); + if (kDebugMode) debugPrint("Listners Initiated"); } - genericCheckEvent(List? params) async { - print("------------- Generic Event Triggered ---------------"); - print("------------- Generic Event Triggered ---------------"); - print(params); - print("------------- Generic Event Triggered ---------------"); - print("------------- Generic Event Triggered ---------------"); - } + // genericCheckEvent(List? params) async { + // print("------------- Generic Event Triggered ---------------"); + // print("------------- Generic Event Triggered ---------------"); + // print(params); + // print("------------- Generic Event Triggered ---------------"); + // print("------------- Generic Event Triggered ---------------"); + // } handlePreOffer(List? params) async { print("----------Event Pre Offer Received ----------"); dynamic items = params!.toList(); - print("Doctor ID : " + items[0]['from'].toString()); - print("Patient ID: " + items[0]['to'].toString()); + 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(); @@ -988,8 +1022,8 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { }); } startCallByRTC(); - Future.delayed(Duration(seconds: 5), () { - Navigator.push( + Future.delayed(Duration(seconds: 2), () { + Navigator.pushReplacement( locator().navigatorKey.currentContext!, MaterialPageRoute( builder: (BuildContext context) => StartCallPage(), @@ -1014,17 +1048,17 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { debuglogger.d(items); } - handleNoAnswerCall(List? params) { - print("----------handle No Answer Received ----------"); - dynamic items = params!.toList(); - debuglogger.d(items); - } - handleCallComplete(List? 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; @@ -1033,7 +1067,9 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { isIncomingCall = false; isOutGoingCall = false; isAudioCall = false; - if (pCon!.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { + isAccepted = false; + if (pCon != null) if (pCon!.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { + if (_localStream != null) pCon!.removeStream(_localStream!); pCon!.close(); pCon!.dispose(); } @@ -1051,9 +1087,11 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { _localStream!.dispose(); _localStream = null; } - if (chatHubConnection != null && !isUserOnline) { - chatHubConnection!.stop(); - } + + // if (chatHubConnection != null && !isUserOnline) { + // chatHubConnection!.stop(); + // } + Navigator.of(locator().navigatorKey.currentContext!).popAndPushNamed(HOME); } void createPConnection() async {