feat: Manage socket connection lifecycle based on authentication status and ensure chat screen joins rooms only when socket is connected.

This commit is contained in:
pradeepkumar
2026-03-15 00:30:12 +05:30
parent fe2bc5bf28
commit 54fdd66270
2 changed files with 25 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ import 'package:real_estate_mobile/core/storage/secure_storage.dart';
import 'package:real_estate_mobile/features/auth/data/auth_repository.dart';
import 'package:real_estate_mobile/features/auth/data/models/register_request.dart';
import 'package:real_estate_mobile/features/auth/data/models/user_model.dart';
import 'package:real_estate_mobile/features/messaging/data/socket_service.dart';
// Auth state
enum AuthStatus { initial, loading, authenticated, error }
@@ -69,6 +70,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
// Wire up force logout callback so API client can reset auth state
// when token refresh fails
ApiClient.onForceLogout = () {
SocketService().disconnect();
state = const AuthState();
};
checkAuthStatus();
@@ -89,6 +91,8 @@ class AuthNotifier extends StateNotifier<AuthState> {
status: AuthStatus.authenticated,
user: user,
);
// Connect socket for real-time updates (matching web's PresenceProvider)
_connectSocket();
// Register for push notifications after auth confirmed
_initPushNotifications();
} catch (_) {
@@ -100,6 +104,8 @@ class AuthNotifier extends StateNotifier<AuthState> {
Future<void> logout() async {
state = state.copyWith(status: AuthStatus.loading);
// Disconnect socket before logout
SocketService().disconnect();
// Unregister FCM token before clearing auth
await PushNotificationService().unregister();
await _repository.logout();
@@ -136,6 +142,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
status: AuthStatus.authenticated,
user: result['user'] as UserModel,
);
_connectSocket();
_initPushNotifications();
} on ApiException catch (e) {
state = state.copyWith(
@@ -186,6 +193,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
user: user,
registeredEmail: email,
);
_connectSocket();
_initPushNotifications();
} on ApiException catch (e) {
state = state.copyWith(
@@ -221,6 +229,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
status: AuthStatus.authenticated,
user: authResponse.user,
);
_connectSocket();
_initPushNotifications();
} on ApiException catch (e) {
state = state.copyWith(
@@ -253,6 +262,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
status: AuthStatus.authenticated,
user: authResponse.user,
);
_connectSocket();
_initPushNotifications();
} on ApiException catch (e) {
state = state.copyWith(
@@ -271,6 +281,10 @@ class AuthNotifier extends StateNotifier<AuthState> {
state = const AuthState();
}
void _connectSocket() {
SocketService().connect();
}
void _initPushNotifications() {
final push = PushNotificationService();
push.initialize().then((_) => push.registerAfterLogin());

View File

@@ -37,8 +37,17 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
notifier.setActiveConversation(widget.conversationId);
notifier.loadMessages(widget.conversationId);
notifier.markAsRead(widget.conversationId);
// Join socket room for real-time updates
_socket.joinConversation(widget.conversationId);
// Join socket room for real-time updates (socket is connected at auth time)
if (_socket.isConnected) {
_socket.joinConversation(widget.conversationId);
} else {
// Wait for socket connection then join
_socket.onConnectionChange.first.then((connected) {
if (connected && mounted) {
_socket.joinConversation(widget.conversationId);
}
});
}
});
_scrollController.addListener(_onScroll);
_messageController.addListener(_onTextChanged);