diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 275f10b..77dcb34 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -186,4 +186,18 @@ class ChatApiClient { } return imagesData; } + + // Call Decline On App Terminated State + + Future callDecline({required int cUserID, required int tUserID, required String targetUsertoken}) async { + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatLoginTokenUrl}calldecline", + {"currentUserId": cUserID, "targetUserId": tUserID, "secretKey": "derichatmobileuser", "targetUserToken": targetUsertoken}, + ); + if (!kReleaseMode) { + logger.i({"currentUserId": cUserID, "targetUserId": tUserID, "secretKey": "derichatmobileuser", "targetUserToken": targetUsertoken}); + logger.i("res: " + response.body); + } + return response; + } } diff --git a/lib/classes/chat_call_kit.dart b/lib/classes/chat_call_kit.dart index 8dd777f..65da5c1 100644 --- a/lib/classes/chat_call_kit.dart +++ b/lib/classes/chat_call_kit.dart @@ -1,25 +1,19 @@ import 'dart:convert'; import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_callkit_incoming/entities/entities.dart'; import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; +import 'package:mohem_flutter_app/api/chat/chat_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; -import 'package:mohem_flutter_app/classes/navigationService.dart'; -import 'package:mohem_flutter_app/classes/notifications.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as ALM; -import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart'; import 'package:mohem_flutter_app/models/chat/incoming_call_model.dart'; import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; -import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart'; -import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; -import 'package:provider/provider.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:signalr_netcore/signalr_client.dart'; @@ -29,15 +23,14 @@ class ChatVoipCall { ChatVoipCall._internal(); factory ChatVoipCall() => _instance; + late ChatProviderModel prov; late ChatCallProvider cProv; dynamic inCallData; bool isUserOnline = false; dynamic callData; - late IncomingCallModel sessionData; Future showCallkitIncoming({required String uuid, RemoteMessage? data, CallDataModel? incomingCallData, bool background = false}) async { - await ChatVoipCall().listenerEvent(); await FlutterCallkitIncoming.endAllCalls(); ALM.Response autoLoginData; SingleUserChatModel callerData; @@ -45,7 +38,7 @@ class ChatVoipCall { // Online & App Logged In ALM.Response sharedDetails = ALM.Response.fromJson(jsonDecode(await Utils.getStringFromPrefs("userLoginChatDetails"))); autoLoginData = ALM.Response.fromJson(AppState().getchatUserDetails == null ? sharedDetails.toJson() : AppState().getchatUserDetails!.response!.toJson()); - dynamic items = jsonDecode(data!.data["user_chat_history_response"]); + dynamic items = jsonDecode(data.data["user_chat_history_response"]); callerData = SingleUserChatModel( targetUserId: items["CurrentUserId"], targetUserEmail: items["CurrentUserEmail"], @@ -58,7 +51,7 @@ class ChatVoipCall { } else { // Offline or App in Background or App is At Verify Screen autoLoginData = ALM.Response.fromJson(jsonDecode(data.data["user_token_response"])); - callerData = SingleUserChatModel.fromJson(json.decode(data!.data["user_chat_history_response"])); + callerData = SingleUserChatModel.fromJson(json.decode(data.data["user_chat_history_response"])); } CallKitParams params = CallKitParams( id: uuid, @@ -71,7 +64,13 @@ class ChatVoipCall { textDecline: 'Decline', textMissedCall: 'Missed call', textCallback: 'Call back', - extra: {"loginDetails": autoLoginData.toJson(), "callerDetails": callerData.toJson(), 'isIncomingCall': true, 'isUserOnline': isUserOnline, 'callType': data!.data["callType"]}, + extra: { + "loginDetails": autoLoginData.toJson(), + "callerDetails": callerData.toJson(), + 'isIncomingCall': true, + 'isUserOnline': isUserOnline, + 'callType': data.data["callType"], + }, android: const AndroidParams( isCustomNotification: true, isShowLogo: false, @@ -99,121 +98,47 @@ class ChatVoipCall { ringtonePath: 'system_ringtone_default', ), ); - sessionData = IncomingCallModel.fromJson(params.toJson()); if (callerData.chatEventId == 3) { await Utils.saveStringFromPrefs("isIncomingCall", "true"); await FlutterCallkitIncoming.showCallkitIncoming(params); } } - Future getCurrentCall() async { - var calls = await FlutterCallkitIncoming.activeCalls(); - if (calls is List) { - if (calls.isNotEmpty) { - return calls[0]; - } else { - return null; - } - } - } - - void checkAndNavigationCallingPage() async { - dynamic currentCall = await getCurrentCall(); - if (currentCall != null) { - Future.delayed(const Duration(seconds: 1)).whenComplete(() { - Navigator.pushNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall); - }); - } - } - - Future isCall() async { - dynamic calls = await FlutterCallkitIncoming.activeCalls(); - if (calls is List) { - if (calls.isNotEmpty) { - NavigationService.navigateToPage(StartCallPage()); - } - } - } - -//Function(CallEvent) callback - Future listenerEvent() async { - try { - FlutterCallkitIncoming.onEvent.listen((CallEvent? event) async { - switch (event!.event) { - case Event.ACTION_CALL_INCOMING: - break; - case Event.ACTION_CALL_START: - break; - case Event.ACTION_CALL_ACCEPT: - if (isUserOnline) { - checkAndNavigationCallingPage(); - } else { - isCall(); - } - break; - case Event.ACTION_CALL_DECLINE: - Utils.saveStringFromPrefs("isIncomingCall", "false"); - Utils.saveStringFromPrefs("inComingCallData", "null"); - declineCall(); - break; - case Event.ACTION_CALL_ENDED: - Utils.saveStringFromPrefs("isIncomingCall", "false"); - Utils.saveStringFromPrefs("inComingCallData", "null"); - FlutterCallkitIncoming.endAllCalls(); - break; - case Event.ACTION_CALL_TIMEOUT: - Utils.saveStringFromPrefs("isIncomingCall", "false"); - Utils.saveStringFromPrefs("inComingCallData", "null"); - FlutterCallkitIncoming.endAllCalls(); - break; - } - }); - } on Exception {} - } - - Future declineCall() async { + Future declineCall({var payload}) async { + IncomingCallModel data = IncomingCallModel.fromJson(jsonDecode(payload)); if (isUserOnline) { - HubConnection hc = await makeHub(); - await hc.start(); - print("Connection State ===" + chatHubConnection.state.toString()); - if (hc.state == HubConnectionState.Connected) { - if (sessionData?.extra != null) { - chatHubConnection.invoke("HangUpAsync", args: [ - int.parse(sessionData.extra!.callerDetails!.currentUserId.toString()), - int.parse(sessionData.extra!.callerDetails!.targetUserId.toString()), + HubConnection _hc = await makeHub(sessionData: data); + await _hc.start(); + if (_hc.state == HubConnectionState.Connected) { + if (data.extra != null) { + _hc.invoke("HangUpAsync", args: [ + data.extra!.callerDetails!.currentUserId!, + data.extra!.callerDetails!.targetUserId!, ]); - chatHubConnection.invoke("UpdateUserStatusAsync", args: [ - int.parse(sessionData.extra!.callerDetails!.currentUserId.toString()), + _hc.invoke("UpdateUserStatusAsync", args: [ + int.parse(data.extra!.callerDetails!.currentUserId.toString()), 1, ]); - FlutterCallkitIncoming.endCall(sessionData.id!); - chatHubConnection = hc; + FlutterCallkitIncoming.endAllCalls(); + chatHubConnection = _hc; } } } else { - HubConnection hc = await makeHub(); - await hc.start(); - await hc.invoke( - "HangUpAsync", - args: [ - int.parse(sessionData.extra!.callerDetails!.currentUserId.toString()), - int.parse(sessionData.extra!.callerDetails!.targetUserId.toString()), - ], - ); - FlutterCallkitIncoming.endCall(sessionData.id!); - if (!isUserOnline) { - hc.stop(); - } else { - chatHubConnection = hc; - } + await ChatApiClient().callDecline(cUserID: data.extra!.callerDetails!.targetUserId!, tUserID: data.extra!.callerDetails!.currentUserId!, targetUsertoken: data.extra!.loginDetails!.token!); } } - Future makeHub() async { - HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); - HubConnection hc = HubConnectionBuilder() - .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${sessionData.extra!.loginDetails!.id}&source=Desktop&access_token=${sessionData.extra?.loginDetails!.token}", options: httpOp) - .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); - return hc; + Future makeHub({required IncomingCallModel sessionData}) async { + late HubConnection hc; + try { + HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); + hc = HubConnectionBuilder() + .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${sessionData.extra!.loginDetails!.id}&source=Desktop&access_token=${sessionData.extra?.loginDetails!.token}", options: httpOp) + .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); + return hc; + } catch (e) { + print(e); + return hc; + } } } diff --git a/lib/classes/navigationService.dart b/lib/classes/navigationService.dart deleted file mode 100644 index f193c9b..0000000 --- a/lib/classes/navigationService.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get_it/get_it.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; -import 'package:mohem_flutter_app/main.dart'; - - -void setupLocator() { - print("GetIt Registered :::::"); - locator.registerLazySingleton(() => NavigationService()); -} - -class NavigationService { - final GlobalKey navigatorKey = GlobalKey(); - - static Future navigateTo(String routeName) { - var key = locator().navigatorKey; - return key.currentState!.pushNamed(routeName); - } - - static Future navigateToPage(Widget page) { - var key = locator().navigatorKey; - var pageRoute = MaterialPageRoute(builder: (context) => page); - return Navigator.push(key.currentContext!, pageRoute); - } -} - - diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 9c2d45e..73cd5ca 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -1,5 +1,4 @@ import 'dart:io'; - import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; @@ -47,6 +46,7 @@ class AppNotifications { // if (Platform.isAndroid) { // hmsApiAvailability = HmsApiAvailability(); // } + print("Firebase init"); await requestPermissions(); AppState().setDeviceToken = firebaseToken; await Permission.notification.isDenied.then((bool value) { @@ -54,6 +54,10 @@ class AppNotifications { Permission.notification.request(); } }); + + await FirebaseMessaging.instance.setAutoInitEnabled(true); + await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(alert: true, badge: true, sound: true); + RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) _handleMessage(initialMessage); @@ -114,14 +118,11 @@ class AppNotifications { } void _handleMessage(RemoteMessage message) { - print("res: ------handle message--------"); - logger.w(message); Utils.saveStringFromPrefs("isAppOpendByChat", "false"); if (message.data.isNotEmpty && message.data["messageType"] == 'chat') { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); } else if (message.data.isNotEmpty && message.data["messageType"] == 'call') { - logger.d(message.data); ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message); } } @@ -131,15 +132,21 @@ class AppNotifications { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); } - print("hereeee"); } } -Future backgroundMessageHandler(RemoteMessage message) async { +const AndroidNotificationChannel channel = AndroidNotificationChannel( + 'high_importance_channel', // id + 'High Importance Notifications', // title + description: 'This channel is used for important notifications.', // description + importance: Importance.high, +); + +@pragma('vm:entry-point') +Future backgroundMessageHandler(RemoteMessage message) async { await Firebase.initializeApp(); - print("res: ------background message--------"); if (message.data.isNotEmpty && message.data["messageType"] == 'chat') { Utils.saveStringFromPrefs("isAppOpendByChat", "false"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); diff --git a/lib/main.dart b/lib/main.dart index 900a6d3..08203d5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,11 +3,9 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:get_it/get_it.dart'; import 'package:logger/logger.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; -import 'package:mohem_flutter_app/classes/navigationService.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/codegen_loader.g.dart'; import 'package:mohem_flutter_app/models/post_params_model.dart'; @@ -23,7 +21,6 @@ import 'package:provider/single_child_widget.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:sizer/sizer.dart'; -final GetIt locator = GetIt.instance; late HubConnection chatHubConnection; Logger logger = Logger( // filter: null, // Use the default LogFilter (-> only log in debug mode) @@ -50,11 +47,8 @@ Future main() async { DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); - locator.registerSingleton(NavigationService(), - signalsReady: true); await EasyLocalization.ensureInitialized(); AppState().setPostParamsInitConfig(); - HttpOverrides.global = MyHttpOverrides(); isTablet = MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.shortestSide >= ApiConsts.tabletMinLength; @@ -101,7 +95,6 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - callGlobalContext = context; return Sizer( builder: ( BuildContext context, @@ -117,9 +110,8 @@ class MyApp extends StatelessWidget { MonthYearPickerLocalizations.delegate, ); return MaterialApp( - navigatorKey: locator().navigatorKey, + navigatorKey: AppRoutes.navigatorKey, builder: (BuildContext context, Widget? child) { - AppRoutes.navigatorKey = locator().navigatorKey; return MediaQuery( data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: child!, diff --git a/lib/provider/chat_call_provider.dart b/lib/provider/chat_call_provider.dart index 957c2e6..9bdf0f9 100644 --- a/lib/provider/chat_call_provider.dart +++ b/lib/provider/chat_call_provider.dart @@ -210,6 +210,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { isIncomingCall = false; isOutGoingCall = false; isAudioCall = false; + if (isCallConnected) { if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) { print("------------------ PC Stopped ----------------------------"); @@ -217,10 +218,15 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { _pc.dispose(); } } - remoteRenderer!.dispose(); - localVideoRenderer!.dispose(); - localVideoRenderer = null; - remoteRenderer = null; + if (remoteRenderer != null) { + remoteRenderer!.dispose(); + remoteRenderer = null; + } + if (localVideoRenderer != null) { + localVideoRenderer!.dispose(); + localVideoRenderer = null; + } + if (_localStream != null) { _localStream!.dispose(); _localStream = null; @@ -248,10 +254,15 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { _pc.dispose(); } } - remoteRenderer!.dispose(); - localVideoRenderer!.dispose(); - localVideoRenderer = null; - remoteRenderer = null; + if (remoteRenderer != null) { + remoteRenderer!.dispose(); + remoteRenderer = null; + } + if (localVideoRenderer != null) { + localVideoRenderer!.dispose(); + localVideoRenderer = null; + } + if (_localStream != null) { _localStream!.dispose(); _localStream = null; @@ -259,7 +270,6 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { isOutGoingCall = false; isIncomingCall = false; isAudioCall = false; - // await initStreams().whenComplete(() => notifyListeners()); return true; } } @@ -285,7 +295,10 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { print("--------------------- onHangUp ---------------------------------------"); endCall(isUserOnline: isUserOnline).then((bool value) { - Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); + if (isCallConnected) { + Navigator.of(AppRoutes.navigatorKey.currentContext!).pop(); + isCallConnected = false; + } isCallEnded = true; }); } @@ -349,13 +362,21 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { // 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 invoke({required String invokeMethod, required int currentUserID, required int targetUserID, var data, int userStatus = 1, var debugData}) async { List args = []; - // Utils.showToast(currentUserID.toString() + " -- " + targetUserID.toString() + " -- " + isVideoCall.toString()); if (invokeMethod == "CallUserAsync") { args = [currentUserID, targetUserID, isVideoCall]; } else if (invokeMethod == "answerCallAsync") { @@ -573,23 +594,23 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { Future startIncomingCallViaKit({bool isVCall = true, required var inCallData}) async { Utils.saveStringFromPrefs("isIncomingCall", "false"); - if(isVCall) { + if (isVCall) { isVideoCall = isVCall; - }else{ + } else { isAudioCall = true; } await initStreams(); isIncomingCall = true; incomingCallData = SingleUserChatModel.fromJson(inCallData); loudOn(); - // notifyListeners(); + // notifyListeners(); } void connectIncomingCall() { invoke(invokeMethod: "answerCallAsync", currentUserID: AppState().getchatUserDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!); isIncomingCallLoader = false; isIncomingCall = true; - // isVideoCall = true; + // isVideoCall = true; notifyListeners(); } diff --git a/lib/ui/chat/call/chat_incoming_call_screen.dart b/lib/ui/chat/call/chat_incoming_call_screen.dart index 0dbec81..32ac3df 100644 --- a/lib/ui/chat/call/chat_incoming_call_screen.dart +++ b/lib/ui/chat/call/chat_incoming_call_screen.dart @@ -46,9 +46,7 @@ class _StartCallPageState extends State { dynamic calls = await FlutterCallkitIncoming.activeCalls(); if (calls.isNotEmpty) { sessionData = IncomingCallModel.fromRawJson(jsonEncode(calls[0])); - isIncomingCall = sessionData.extra!.isIncomingCall!; } - if (isIncomingCall) { if (provider.isUserOnline) { cProv.isUserOnline = provider.isUserOnline; if (kDebugMode) { @@ -73,50 +71,10 @@ class _StartCallPageState extends State { } catch (e) { logger.w(e); } - if (kDebugMode) { - print('========== END =============='); - } } - } - // else if (isOutGoingCall) { - // if (kDebugMode) { - // print("====== Processing Outgoing Call ========="); - // } - // - // } - else { - if (kDebugMode) { - print("====== Something Wrong With Call ========="); - } - } } - // void connection({required data, required bool isUserOnline}) async { - // if (isUserOnline) { - // cProv.isUserOnline = isUserOnline; - // cProv.startIncomingCallViaKit(inCallData: data); - // } else { - // dynamic callData = await jsonDecode(data); - // AppState().setchatUserDetails = UserAutoLoginModel( - // response: Response.fromJson(callData[0]["loginDetails"]), - // errorResponses: null, - // ); - // Utils.saveStringFromPrefs( - // "userLoginChatDetails", - // UserAutoLoginModel( - // response: Response.fromJson(callData[0]["loginDetails"]), - // errorResponses: null, - // ).toJson().toString()); - // cProv.startIncomingCallViaKit(inCallData: data); - // try { - // await prov.buildHubConnection(context: AppRoutes.navigatorKey.currentContext!, ccProvider: cProv).whenComplete(() { - // cProv.init(); - // }); - // } catch (e) { - // logger.w(e); - // } - // } - // } + @override Widget build(BuildContext context) { diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index e7fc4a3..898b316 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -1,14 +1,18 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:io'; import 'dart:ui' as ui; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_callkit_incoming/entities/call_event.dart'; +import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/chat_call_kit.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -17,11 +21,14 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; +import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_call_provider.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart'; import 'package:mohem_flutter_app/ui/landing/widget/app_drawer.dart'; import 'package:mohem_flutter_app/ui/landing/widget/menus_widget.dart'; import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart'; @@ -35,8 +42,6 @@ import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; - - class DashboardScreen extends StatefulWidget { DashboardScreen({Key? key}) : super(key: key); @@ -59,17 +64,62 @@ class _DashboardScreenState extends State with WidgetsBindingOb void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); + callListeners(); + scheduleMicrotask(() { + data = Provider.of(context, listen: false); + marathonProvider = Provider.of(context, listen: false); + cProvider = Provider.of(context, listen: false); + chatCallProvider = Provider.of(context, listen: false); + if (checkIfPrivilegedForChat()) { + _bHubCon(); + } + _onRefresh(true); + }); + } - scheduleMicrotask(() { - data = Provider.of(context, listen: false); - marathonProvider = Provider.of(context, listen: false); - cProvider = Provider.of(context, listen: false); - chatCallProvider = Provider.of(context, listen: false); - if (checkIfPrivilegedForChat()) { - _bHubCon(); + Future callListeners() async { + try { + FlutterCallkitIncoming.onEvent.listen((CallEvent? event) async { + switch (event!.event) { + case Event.ACTION_CALL_INCOMING: + break; + case Event.ACTION_CALL_START: + break; + case Event.ACTION_CALL_ACCEPT: + if (mounted) { + moveToCallScreen(); + } + break; + case Event.ACTION_CALL_DECLINE: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + await ChatVoipCall().declineCall(payload: jsonEncode(event.body)); + break; + case Event.ACTION_CALL_ENDED: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + FlutterCallkitIncoming.endAllCalls(); + break; + case Event.ACTION_CALL_TIMEOUT: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + FlutterCallkitIncoming.endAllCalls(); + break; + } + }); + } on Exception {} + } + + Future moveToCallScreen() async { + dynamic calls = await FlutterCallkitIncoming.activeCalls(); + if (calls is List) { + if (calls.isNotEmpty) { + Future.delayed(const Duration(seconds: 1)).whenComplete(() { + MaterialPageRoute pageRoute = MaterialPageRoute(builder: (BuildContext context) => StartCallPage()); + Navigator.push(context, pageRoute); + }); } - _onRefresh(true); - }); + } } @override @@ -161,12 +211,12 @@ class _DashboardScreenState extends State with WidgetsBindingOb } void checkERMChannel() { - data.getITGNotification().then((val) { + data.getITGNotification().then((MohemmItgResponseItem? val) { if (val!.result!.data != null) { print("-------------------- Survey ----------------------------"); if (val.result!.data!.notificationType == "Survey") { DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { + (ItgMainRes? value) { if (value!.mohemmItgResponseItem!.statusCode == 200) { if (value.mohemmItgResponseItem!.result!.data != null) { // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); @@ -182,7 +232,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb } else { print("------------------------------------------- Ads --------------------"); DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { + (ItgMainRes? value) { if (value!.mohemmItgResponseItem!.statusCode == 200) { if (value.mohemmItgResponseItem!.result!.data != null) { Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 8a78dfd..fd53752 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; @@ -8,10 +9,13 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_callkit_incoming/entities/call_event.dart'; +import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; // import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/chat_call_kit.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/notifications.dart'; @@ -28,8 +32,8 @@ import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; +import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; -import 'package:mohem_flutter_app/widgets/button/hmg_connectivity_button.dart'; import 'package:mohem_flutter_app/widgets/input_widget.dart'; // import 'package:safe_device/safe_device.dart'; @@ -61,6 +65,7 @@ class _LoginScreenState extends State { bool isRealDevice = false; bool isOnExternalStorage = false; bool isDevelopmentModeEnable = false; + bool isIncomingCall = false; // late HmsApiAvailability hmsApiAvailability; @@ -72,6 +77,7 @@ class _LoginScreenState extends State { // if (kReleaseMode) { // checkDeviceSafety(); // } + callListeners(); } // void checkDeviceSafety() async { @@ -90,6 +96,58 @@ class _LoginScreenState extends State { // } // } + Future callListeners() async { + try { + FlutterCallkitIncoming.onEvent.listen((CallEvent? event) async { + switch (event!.event) { + case Event.ACTION_CALL_INCOMING: + break; + case Event.ACTION_CALL_START: + break; + case Event.ACTION_CALL_ACCEPT: + if (mounted) { + isIncomingCall = true; + moveToCallScreen(); + } + break; + case Event.ACTION_CALL_DECLINE: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + await ChatVoipCall().declineCall(payload: jsonEncode(event.body)); + + break; + case Event.ACTION_CALL_ENDED: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + FlutterCallkitIncoming.endAllCalls(); + break; + case Event.ACTION_CALL_TIMEOUT: + Utils.saveStringFromPrefs("isIncomingCall", "false"); + Utils.saveStringFromPrefs("inComingCallData", "null"); + FlutterCallkitIncoming.endAllCalls(); + break; + } + }); + } on Exception {} + } + + Future moveToCallScreen() async { + dynamic calls = await FlutterCallkitIncoming.activeCalls(); + if (calls is List) { + if (calls.isNotEmpty) { + Utils.hideLoading(context); + var pageRoute = MaterialPageRoute(builder: (context) => StartCallPage()); + Navigator.push(context, pageRoute).whenComplete((){ + checkFirebaseToken(); + }); + }else{ + FlutterCallkitIncoming.endAllCalls(); + Utils.showToast("Something wen't wrong"); + } + } + } + + @override void dispose() { super.dispose(); @@ -100,7 +158,7 @@ class _LoginScreenState extends State { Future checkFirebaseToken() async { try { - Utils.showLoading(context); + //Utils.showLoading(context); if (Platform.isAndroid) { try { if (!(await Utils.isGoogleServicesAvailable())) { @@ -206,7 +264,12 @@ class _LoginScreenState extends State { // 13777 // Ab12345cd } - if (isAppOpenBySystem!) checkFirebaseToken(); + Utils.showLoading(context); + Future.delayed(const Duration(seconds: 2)).whenComplete(() { + if (!isIncomingCall) { + if (isAppOpenBySystem!) checkFirebaseToken(); + } + }); } // username.text = "15444"; diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index f94e59a..b6b5953 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; import 'package:flutter_svg/svg.dart'; import 'package:local_auth/auth_strings.dart'; import 'package:local_auth/local_auth.dart'; @@ -21,6 +20,7 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/basic_member_information_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; +import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart'; import 'package:mohem_flutter_app/ui/dialogs/id/business_card_dialog.dart'; import 'package:mohem_flutter_app/ui/dialogs/id/employee_digital_id_dialog.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; @@ -51,19 +51,16 @@ class _VerifyLastLoginScreenState extends State { @override void initState() { - _getAvailableBiometrics(); + _getAvailableBiometrics(); // setDefault(); super.initState(); } - - @override Widget build(BuildContext context) { mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments as GetMobileLoginInfoListModel; // String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; String empName = mobileLoginInfoListModel!.employeeName!; - return Scaffold( appBar: AppBar( backgroundColor: Colors.transparent,