From af9ce4fa3c934ea5ad26bd2b9c06a4c05e9f0e97 Mon Sep 17 00:00:00 2001 From: AlexisDanlos Date: Wed, 18 Jun 2025 18:58:05 +0200 Subject: [PATCH] feat: improve call handling with manual hangup support and UI updates --- dialer/lib/domain/services/call_service.dart | 59 +++++++++++++++---- .../presentation/features/call/call_page.dart | 17 ++++-- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/dialer/lib/domain/services/call_service.dart b/dialer/lib/domain/services/call_service.dart index 5b95683..e6669f3 100644 --- a/dialer/lib/domain/services/call_service.dart +++ b/dialer/lib/domain/services/call_service.dart @@ -47,10 +47,8 @@ class CallService { _manualHangupFlag = true; // Mark that hangup was manual print('CallService: Manual hangup flag set to $_manualHangupFlag'); } else { - print( - 'CallService: No pending SIM switch to cancel, but setting manual hangup flag'); - _manualHangupFlag = - true; // Still mark as manual even if no pending switch + print('CallService: No pending SIM switch to cancel'); + // Don't set manual hangup flag if there's no SIM switch to cancel } } @@ -97,8 +95,15 @@ class CallService { 'CallService: State changed to $state, wasPhoneLocked: $wasPhoneLocked'); _callStateController.add(state); if (state == "disconnected" || state == "disconnecting") { + print('CallService: ========== CALL DISCONNECTED =========='); + print( + 'CallService: _pendingSimSwitch: ${_pendingSimSwitch != null}'); + print('CallService: _manualHangupFlag: $_manualHangupFlag'); + print('CallService: _isCallPageVisible: $_isCallPageVisible'); + // Close call page if no pending SIM switch OR if it was a manual hangup if (_pendingSimSwitch == null || _manualHangupFlag) { + print('CallService: Condition met, calling _closeCallPage()'); _closeCallPage(); // Only reset manual hangup flag after successful page close if (_manualHangupFlag) { @@ -106,6 +111,8 @@ class CallService { 'CallService: Resetting manual hangup flag after page close'); _manualHangupFlag = false; } + } else { + print('CallService: NOT closing call page - condition not met'); } if (wasPhoneLocked) { await _channel.invokeMethod("callEndedFromFlutter"); @@ -156,10 +163,24 @@ class CallService { case "callEnded": case "callRemoved": wasPhoneLocked = call.arguments["wasPhoneLocked"] as bool? ?? false; - print( - 'CallService: Call ended/removed, wasPhoneLocked: $wasPhoneLocked'); // Only close call page if there's no pending SIM switch AND no manual hangup in progress - if (_pendingSimSwitch == null && !_manualHangupFlag) { + print('CallService: ========== CALL ENDED/REMOVED =========='); + print('CallService: wasPhoneLocked: $wasPhoneLocked'); + print('CallService: _pendingSimSwitch: ${_pendingSimSwitch != null}'); + print('CallService: _manualHangupFlag: $_manualHangupFlag'); + print('CallService: _isCallPageVisible: $_isCallPageVisible'); + + // Only close call page if there's no pending SIM switch OR if it was a manual hangup during SIM switch + if (_pendingSimSwitch == null || _manualHangupFlag) { + print('CallService: Condition met, calling _closeCallPage()'); _closeCallPage(); + // Reset manual hangup flag after closing page + if (_manualHangupFlag) { + print( + 'CallService: Resetting manual hangup flag after callEnded'); + _manualHangupFlag = false; + } + } else { + print('CallService: NOT closing call page - condition not met'); } if (wasPhoneLocked) { await _channel.invokeMethod("callEndedFromFlutter"); @@ -388,7 +409,7 @@ class CallService { return; } _activeCallNumber = currentPhoneNumber; - Navigator.pushReplacement( + Navigator.push( context, MaterialPageRoute( settings: const RouteSettings(name: '/call'), @@ -468,7 +489,7 @@ class CallService { } print( - 'CallService: Closing call page, _isCallPageVisible: $_isCallPageVisible'); + 'CallService: Closing call page, _isCallPageVisible: $_isCallPageVisible, _pendingSimSwitch: ${_pendingSimSwitch != null}, _manualHangupFlag: $_manualHangupFlag'); if (Navigator.canPop(context)) { print('CallService: Popping call page'); Navigator.pop(context); @@ -556,18 +577,34 @@ class CallService { // Getter to check if there's a pending SIM switch static bool get hasPendingSimSwitch => _pendingSimSwitch != null; - Future> hangUpCall(BuildContext context) async { try { - print('CallService: Hanging up call'); + print('CallService: ========== HANGUP INITIATED =========='); + print('CallService: _pendingSimSwitch: ${_pendingSimSwitch != null}'); + print('CallService: _manualHangupFlag: $_manualHangupFlag'); + print('CallService: _isCallPageVisible: $_isCallPageVisible'); + final result = await _channel.invokeMethod('hangUpCall'); print('CallService: hangUpCall result: $result'); final resultMap = Map.from(result as Map); + if (resultMap["status"] != "ended") { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Failed to end call")), ); + } else { + // If hangup was successful, ensure call page closes after a short delay + // This is a fallback in case the native call state events don't fire properly + Future.delayed(const Duration(milliseconds: 1500), () { + if (_isCallPageVisible) { + print( + 'CallService: FALLBACK - Force closing call page after hangup'); + _closeCallPage(); + _manualHangupFlag = false; // Reset flag + } + }); } + return resultMap; } catch (e) { print("CallService: Error hanging up call: $e"); diff --git a/dialer/lib/presentation/features/call/call_page.dart b/dialer/lib/presentation/features/call/call_page.dart index 2497956..c6ec56b 100644 --- a/dialer/lib/presentation/features/call/call_page.dart +++ b/dialer/lib/presentation/features/call/call_page.dart @@ -284,6 +284,12 @@ class _CallPageState extends State { print( 'CallPage: Initiating manual hangUp - canceling any pending SIM switch'); + // Immediately mark call as inactive to allow page navigation + setState(() { + _isCallActive = false; + _callStatus = "Ending Call..."; + }); + // Cancel any pending SIM switch since user is manually hanging up _callService.cancelPendingSimSwitch(); @@ -327,13 +333,12 @@ class _CallPageState extends State { print( 'CallPage: Building UI, _callStatus: $_callStatus, route: ${ModalRoute.of(context)?.settings.name ?? "unknown"}'); return PopScope( - canPop: !_isCallActive, + canPop: + true, // Always allow popping - CallService manages when it's appropriate onPopInvoked: (didPop) { - if (!didPop && _isCallActive) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Cannot leave during an active call')), - ); - } + print( + 'CallPage: PopScope onPopInvoked - didPop: $didPop, _isCallActive: $_isCallActive, _callStatus: $_callStatus'); + // No longer prevent popping during active calls - CallService handles this }, child: Scaffold( body: Container(