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)
This commit is contained in:
@@ -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<SaveFamilyApp>
|
||||
_walletHeartbeat?.stop();
|
||||
_legacyHeartbeat?.stop();
|
||||
_webSocket?.disconnect();
|
||||
GetIt.I<VideocallClient>().logout();
|
||||
FirebaseMessaging.instance.deleteToken().catchError((Object e) {
|
||||
debugPrint('[FCM] deleteToken on logout failed: $e');
|
||||
});
|
||||
|
||||
@@ -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<void> _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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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!);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user