connect method
Connect websocket with given userId
apiHost
and wsHost
are optional in case to connect own server
Implementation
Future<User> connect({
required String userId,
String? nickname,
String? accessToken,
String? apiHost,
String? wsHost,
bool reconnect = false,
}) async {
logger.i("sendbird connecting....");
if (userId.isEmpty) {
throw InvalidParameterError();
}
userId = userId.trim();
String? sessionKey;
logger.i('Attempting to connecting with $userId');
// already connected
if (_state.connected &&
_webSocket?.isConnected() == true &&
_state.userId == userId &&
_state.currentUser != null) {
logger.i('already connected with $userId, return user');
return _state.currentUser!;
}
// is already in progress to connect
if ((_state.connecting || _state.reconnecting) &&
_state.userId == userId &&
_loginCompleter != null &&
!_forceReconnect) {
logger.i('waiting to connect previous call with $userId');
return _loginCompleter!.future;
}
if (reconnect) {
sessionKey = await _sessionManager.getSessionKey();
if (sessionKey == null || sessionKey.isEmpty) {
ConnectionManager.flushCompleters(error: ConnectionRequiredError());
_eventManager.notifyReconnectionFailed();
throw ConnectionFailedError();
}
_eventManager.notifyReconnectionStarted();
} else {
// start from clean slate
logger.i('clearing out previous connection');
await logout();
}
// This has to be above any await for concurrent situation
if (!_forceReconnect) _loginCompleter = Completer();
await _webSocket?.close();
_state.userId = userId;
_state.connecting = true;
_webSocket = WebSocketClient(
onConnect: _onWebSocketConnect,
onDisconnect: _onWebSocketDisconnect,
onData: _onWebSocketData,
onError: _onWebSocketError,
);
_sessionManager.setAccessToken(accessToken);
final apiHostUrl =
reconnect ? _state.apiHost! : apiHost ?? _getDefaultApiHost();
final wsHostUrl =
reconnect ? _state.wsHost! : wsHost ?? _getDefaultWsHost();
_state
..reconnecting = reconnect
..apiHost = apiHostUrl
..wsHost = wsHostUrl;
_api.initialize(baseUrl: apiHostUrl, headers: {
'SB-User-Agent': _sbUserAgent,
'SendBird': _sendbirdHeader,
});
var params = {
if (nickname != null && nickname != '') 'nickname': nickname,
if (reconnect && sessionKey != null)
'key': sessionKey
else
'user_id': userId,
'SB-User-Agent': _sbUserAgent,
'include_extra_data': _extraDatas.join(','),
'expiring_session': _eventManager.getSessionHandler() != null ? '1' : '0',
'include_poll_details': '1',
if (accessToken != null) 'access_token': accessToken,
};
params.addAll(_webSocketParams);
final fullWsHost = wsHostUrl + '/?' + Uri(queryParameters: params).query;
logger.i('websocket connecting.. ');
runZonedGuarded(() async {
await _webSocket?.connect(fullWsHost);
}, (error, stack) {
if (_loginCompleter != null && !_loginCompleter!.isCompleted) {
_loginCompleter!.completeError(error);
}
_state.connecting = false;
_state.reconnecting = false;
_loginCompleter = null;
_forceReconnect = false;
});
final user = await _loginCompleter!.future.timeout(
Duration(seconds: options.connectionTimeout), onTimeout: () async {
logger.e('login timeout');
throw LoginTimeoutError();
}).onError((error, stackTrace) {
if (error is SBError) {
throw error;
} else if (error is Exception) {
throw WebSocketError(message: error.toString());
} else {
throw WebSocketConnectionFailed();
}
});
logger.i('websocket connected and get user from sendbird server');
ConnectionManager.flushCompleters(
error: reconnect ? null : ConnectionClosedError());
if (!registered) {
_ambiguate(WidgetsBinding.instance)?.addObserver(this);
registered = true;
}
_loginCompleter = null;
_reconnectTimer = null;
_forceReconnect = false;
return user;
}