Skip to content

events not triggering am using socket_io_client: ^1.0.2 in app and socket_io v2.* on the server #409

@Jules369-ZM

Description

@Jules369-ZM

import 'dart:async';
import 'dart:developer';
import 'package:auth_repo/auth_repo.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import 'package:local_data/local_data.dart';
import 'package:socket_io_client/socket_io_client.dart' as io_client;

/// {@template socket_source}
/// Package to handle Socket.IO calls
/// {@endtemplate}
class SocketSource {
/// {@macro socket_source}
SocketSource._(
this._token,
this._prefs,
this._appBuildConfig,
this._storeId,
);

final String _token;
final String _storeId;
// ignore: unused_field
final SharedPrefs _prefs;
final AppBuildConfig _appBuildConfig;

/// Public factory to initialize the SocketSource
static Future init(
String socketUrl, {
required SharedPrefs prefs,
required AppBuildConfig appBuildConfig,
required String storeId,
bool alwaysConnected = false,
String? token,
}) async {
final socketApi = SocketSource._(
token ?? '',
prefs,
appBuildConfig,
storeId,
);
await socketApi._init(
socketUrl: socketUrl,
alwaysConnected: alwaysConnected,
);
return socketApi;
}

late io_client.Socket _socket;

// Stream controllers to manage connection status and incoming messages
final _socketState = StreamController();
final _socketController =
StreamController<Map<dynamic, dynamic>?>.broadcast();

/// Initialize the Socket.IO connection
Future _init({
required String socketUrl,
bool alwaysConnected = false,
}) async {
log('Initializing socket with URL: $socketUrl');

InternetConnectionChecker().onStatusChange.listen((event) {
  switch (event) {
    case InternetConnectionStatus.connected:
      log('Internet connected');
      log('Socket URL: $socketUrl');

      try {
        _socket = io_client.io(
          socketUrl,
          io_client.OptionBuilder()
              .setTimeout(10000)
              .setReconnectionDelay(5000)
              .setReconnectionDelayMax(10000)
              .enableAutoConnect()
              .enableForceNewConnection()
              .enableReconnection()

          .setTransports(['websocket']).build(),
        );

        // Initialize socket event handlers
        _setupSocketEventHandlers();
      } catch (e, stackTrace) {
        log('Socket initialization error: $e');
        log('Stack trace: $stackTrace');
      }

      if (!_socket.connected) {
        _connectToSocket();
      } else {
        log('Socket already connected');
        _socketState.add(true);
      }

    case InternetConnectionStatus.disconnected:
      log('Internet disconnected');
      _socketState.add(false);
      _socket.disconnect();
  }
});

final hasConnection = await InternetConnectionChecker().hasConnection;
if (hasConnection && alwaysConnected) {
  _connectToSocket();
}

}

void _setupSocketEventHandlers() {
socket
..onConnect((
) {
log('Socket connected successfully');
_handleConnection();
debugSocketState();
socketState.add(true);
})
..onDisconnect((
) {
log('Socket disconnected');
socketState.add(false);
})
..onConnectError((error) {
log('Socket connection error: $error');
})
..onError((error) {
log('Socket error: $error');
})
..onReconnect((
) {
log('Socket reconnected');
_handleConnection();
debugSocketState();
socketState.add(true);
})
..onReconnectError((error) {
log('Socket reconnection error: $error');
})
..onReconnectFailed((
) {
log('Socket reconnection failed');
});
}

/// Connect to the Socket.IO server
void _connectToSocket() {
try {
log('Attempting to connect to socket...');
_socket.connect();
} catch (e) {
log('Error connecting to socket: $e');
}
}

void _handleConnection() {
try {
// First emit the merchant data
final merchantData = {
'token': _token,
'appId': _appBuildConfig.appId,
'sender': 'Jules',
'storeId': _storeId,
};

  log('Emitting addMerchant event with data: $merchantData');
  emit('addMerchant', merchantData);

  // Then set up all event listeners
  _socket
    ..on('orderAddTime', (data) {
      log('Received orderAddTime: $data');
      _emitToController('orderAddTime', data);
    })
    ..on('pendingOrderCount', (data) {
      log('Received pendingOrderCount: $data');
      _emitToController('pendingOrderCount', data);
    })
    ..on('storeOrder', (data) {
      log('Received storeOrder: $data');
      _emitToController('storeOrder', data);
    })
    ..on('orderLimitAlert', (data) {
      log('Received orderLimitAlert: $data');
      _emitToController('orderLimitAlert', data);
    })
    ..on('addMerchant', (data) {
      log('Received addMerchant: $data');
      _emitToController('addMerchant', data);
    })
    ..on('acceptOrder', (data) {
      log('Received acceptOrder: $data');
      _emitToController('acceptOrder', data);
    })
    ..on('statusChange', (data) {
      log('Received statusChange: $data');
      _emitToController('statusChange', data);
    })
    ..on('updateStore', (data) {
      log('Received updateStore: $data');
      _emitToController('updateStore', data);
    });
} catch (e, stackTrace) {
  log('Error in _handleConnection: $e');
  log('Stack trace: $stackTrace');
}

}

void _emitToController(String event, dynamic data) {
final response = <String, dynamic>{
'event': event,
'data': data,
};
_socketController.add(response);
}

/// Socket connection status stream
Stream get hasSocketConnection async* {
yield false; // Initial state
yield* _socketState.stream;
}

/// Stream to listen for messages from the socket
Stream<Map<dynamic, dynamic>?> get channelStream async* {
yield* _socketController.stream;
}

/// Emit data to a Socket.IO event
Future emit(String event, dynamic data) async {
try {
final hasConnection = await InternetConnectionChecker().hasConnection;
if (!hasConnection) {
log('Cannot emit - No internet connection');
return;
}

  if (_socket.connected) {
    log('Emitting event: $event');
    log('Event data: $data');
    _socket.emit(event, data);
  } else {
    log('Socket not connected - attempting to reconnect');
    _connectToSocket();
  }
} catch (e) {
  log('Error emitting event: $e');
}

}

/// Disconnect from the Socket.IO server
void disconnect() {
try {
_socket.disconnect();
_socketState.add(false);
log('Socket disconnected successfully');
} catch (e) {
log('Error disconnecting socket: $e');
}
}

/// Dispose method to clean up resources
void dispose() {
try {
disconnect();
_socketController.close();
_socketState.close();
log('Socket resources disposed successfully');
} catch (e) {
log('Error disposing socket resources: $e');
}
}

///
void debugSocketState() {
try {
log('=== Socket Debug Information ===');
log('Socket Connected: ${_socket.connected}');
log('Socket ID: ${_socket.id}');
log('Active Transport: ${_socket.io.engine.transport?.name}');
log('Attempted Events:');
_socket.emit('debug_events', {
'token': _token,
'appId': _appBuildConfig.appId,
'storeId': _storeId,
});

  // Test emit for each event to verify server handling
  final testEvents = [
    'orderAddTime',
    'pendingOrderCount',
    'storeOrder',
    'orderLimitAlert',
    // 'acceptOrder',
    'statusChange',
    'updateStore',
  ];

  for (final event in testEvents) {
    _socket.emit(event, {
      'test': true,
      'event': event,
      'token': _token,
      'appId': _appBuildConfig.appId,
      'storeId': _storeId,
    });
    log('Emitted test for event: $event');
  }
} catch (e) {
  log('Error in debugSocketState: $e');
}

}
}

the first event addMerchant which I emit after successful connection is responding correctly but these others are not triggered i.e storeOrder

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions