From 24ddbf34e4bf5860aa2e8fe67585869ef610490f Mon Sep 17 00:00:00 2001 From: JulianAlcala Date: Mon, 27 Apr 2026 00:22:48 +0200 Subject: [PATCH] fix(videocall): fix SDK re-entry lifecycle and add logout on session clear - Skip login when SDK client is already logged in (early return with isSdkReady) - Set isSdkReady immediately when login() returns true instead of waiting for async callback - Add ref.mounted check after userInfo future to prevent state updates on disposed provider - Logout VideocallClient on session clear to prevent stale SDK sessions - Use getActiveCallItem() in onCallItemUpdate for fresh call state (matches JC demo app) --- apps/mobile_app/lib/save_family_app.dart | 2 ++ .../providers/videocall_controller.dart | 18 +++++++++++++----- .../src/services/videocall_call_service.dart | 10 ++++++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/apps/mobile_app/lib/save_family_app.dart b/apps/mobile_app/lib/save_family_app.dart index 50c4e2e2..50eb65f4 100644 --- a/apps/mobile_app/lib/save_family_app.dart +++ b/apps/mobile_app/lib/save_family_app.dart @@ -20,6 +20,7 @@ import 'package:sf_tracking/sf_tracking.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; import 'package:fonts/fonts.dart'; +import 'package:videocall_sdk/videocall_sdk.dart'; class SaveFamilyApp extends ConsumerStatefulWidget { const SaveFamilyApp({super.key}); @@ -74,6 +75,7 @@ class SaveFamilyAppState extends ConsumerState _walletHeartbeat?.stop(); _legacyHeartbeat?.stop(); _webSocket?.disconnect(); + GetIt.I().logout(); FirebaseMessaging.instance.deleteToken().catchError((Object e) { debugPrint('[FCM] deleteToken on logout failed: $e'); }); diff --git a/modules/legacy/modules/device_management/lib/src/features/videocall/presentation/providers/videocall_controller.dart b/modules/legacy/modules/device_management/lib/src/features/videocall/presentation/providers/videocall_controller.dart index cf427d29..5f20fd81 100644 --- a/modules/legacy/modules/device_management/lib/src/features/videocall/presentation/providers/videocall_controller.dart +++ b/modules/legacy/modules/device_management/lib/src/features/videocall/presentation/providers/videocall_controller.dart @@ -48,6 +48,7 @@ class VideocallController extends _$VideocallController { final deviceId = device?.identificator ?? ''; ref.onDispose(() { + debugPrint('[Videocall] controller disposed'); _callAddSub?.cancel(); _callUpdateSub?.cancel(); _callRemoveSub?.cancel(); @@ -59,6 +60,7 @@ class VideocallController extends _$VideocallController { _deviceService.stopCamera(); } }); + debugPrint('[Videocall] build() called, scheduling _initSdk'); Future.microtask(_initSdk); return VideocallState(deviceId: deviceId); @@ -86,20 +88,26 @@ class VideocallController extends _$VideocallController { Future _autoLogin() async { final user = await ref.read(userInfoProvider.future); + if (!ref.mounted) return; final sanitizedEmail = user.email.replaceAll('@', '_').replaceAll('.', '_'); final userId = 'p_$sanitizedEmail'; - debugPrint('[Videocall] _autoLogin: userId=$userId'); + debugPrint('[Videocall] _autoLogin: userId=$userId, clientState=${_client.state}'); + + if (_client.state == VideocallClientState.loggedIn) { + debugPrint('[Videocall] _autoLogin: already logged in, skipping login'); + state = state.copyWith(localUserId: userId, isSdkReady: true); + return; + } + final ok = await _client.login(userId: userId, password: user.id); - debugPrint( - '[Videocall] _autoLogin: login result=$ok, mounted=${ref.mounted}', - ); + debugPrint('[Videocall] _autoLogin: login result=$ok'); if (!ref.mounted) return; if (!ok) { debugPrint('[Videocall] _autoLogin: login FAILED'); state = state.copyWith(errorEvent: VideocallErrorEvent.authentication); return; } - debugPrint('[Videocall] _autoLogin: setting isSdkReady=true'); + debugPrint('[Videocall] _autoLogin: login accepted, setting isSdkReady=true'); state = state.copyWith(localUserId: userId, isSdkReady: true); } diff --git a/packages/videocall_sdk/lib/src/services/videocall_call_service.dart b/packages/videocall_sdk/lib/src/services/videocall_call_service.dart index 7f5a620d..cc845895 100644 --- a/packages/videocall_sdk/lib/src/services/videocall_call_service.dart +++ b/packages/videocall_sdk/lib/src/services/videocall_call_service.dart @@ -250,12 +250,14 @@ class VideocallCallService with JCCallCallback { } @override - void onCallItemUpdate(JCCallItem item, ChangeParam changeParam) { - final mappedState = _mapCallState(item.getState()); + void onCallItemUpdate(JCCallItem item, ChangeParam changeParam) async { + final activeItem = await _call?.getActiveCallItem(); + final source = activeItem ?? item; + final mappedState = _mapCallState(source.getState()); debugPrint( - '[VideocallSDK] onCallItemUpdate: rawState=${item.getState()}, mappedState=$mappedState, uploadSelf=${item.uploadVideoStreamSelf}, uploadOther=${item.uploadVideoStreamOther}', + '[VideocallSDK] onCallItemUpdate: paramState=${item.getState()}, activeState=${source.getState()}, mappedState=$mappedState, uploadSelf=${source.uploadVideoStreamSelf}, uploadOther=${source.uploadVideoStreamOther}', ); - _currentItem = _buildItem(item, mappedState); + _currentItem = _buildItem(source, mappedState); _callItemUpdateController.add(_currentItem!); }