Merge pull request #520 from GetStream/feat/connectionLessClient
feat!: connection less client [CDS-335]
This commit is contained in:
@@ -220,27 +220,53 @@ class StreamChatClient {
|
||||
|
||||
/// Connects the current user, this triggers a connection to the API.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
Future<Event> connectUser(User user, String token) =>
|
||||
_connectUser(user, token: Token.fromRawValue(token));
|
||||
/// Pass [connectWebSocket]: false, if you want to connect to websocket
|
||||
/// at a later stage or use the client in connection-less mode
|
||||
Future<OwnUser> connectUser(
|
||||
User user,
|
||||
String token, {
|
||||
bool connectWebSocket = true,
|
||||
}) =>
|
||||
_connectUser(
|
||||
user,
|
||||
token: Token.fromRawValue(token),
|
||||
connectWebSocket: connectWebSocket,
|
||||
);
|
||||
|
||||
/// Connects the current user using the [tokenProvider] to fetch the token.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
Future<Event> connectUserWithProvider(
|
||||
User user, TokenProvider tokenProvider) =>
|
||||
_connectUser(user, provider: tokenProvider);
|
||||
Future<OwnUser> connectUserWithProvider(
|
||||
User user,
|
||||
TokenProvider tokenProvider, {
|
||||
bool connectWebSocket = true,
|
||||
}) =>
|
||||
_connectUser(
|
||||
user,
|
||||
provider: tokenProvider,
|
||||
connectWebSocket: connectWebSocket,
|
||||
);
|
||||
|
||||
/// Connects the current user with an anonymous id, this triggers a connection
|
||||
/// to the API. It returns a [Future] that resolves when the connection is
|
||||
/// setup.
|
||||
Future<Event> connectAnonymousUser() async {
|
||||
Future<OwnUser> connectAnonymousUser({
|
||||
bool connectWebSocket = true,
|
||||
}) async {
|
||||
final token = Token.anonymous();
|
||||
final user = OwnUser(id: token.userId);
|
||||
return _connectUser(user, token: token);
|
||||
return _connectUser(
|
||||
user,
|
||||
token: token,
|
||||
connectWebSocket: connectWebSocket,
|
||||
);
|
||||
}
|
||||
|
||||
/// Connects the current user as guest, this triggers a connection to the API.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
Future<Event> connectGuestUser(User user) async {
|
||||
Future<OwnUser> connectGuestUser(
|
||||
User user, {
|
||||
bool connectWebSocket = true,
|
||||
}) async {
|
||||
final userId = user.id;
|
||||
final anonymousToken = Token.anonymous(userId: userId);
|
||||
|
||||
@@ -253,13 +279,18 @@ class StreamChatClient {
|
||||
_tokenManager.reset();
|
||||
|
||||
final guestUserToken = Token.fromRawValue(guestUser.accessToken);
|
||||
return _connectUser(guestUser.user, token: guestUserToken);
|
||||
return _connectUser(
|
||||
guestUser.user,
|
||||
token: guestUserToken,
|
||||
connectWebSocket: connectWebSocket,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Event> _connectUser(
|
||||
Future<OwnUser> _connectUser(
|
||||
User user, {
|
||||
Token? token,
|
||||
TokenProvider? provider,
|
||||
bool connectWebSocket = true,
|
||||
}) async {
|
||||
if (_ws.connectionCompleter?.isCompleted == false) {
|
||||
throw const StreamChatError(
|
||||
@@ -268,7 +299,7 @@ class StreamChatClient {
|
||||
);
|
||||
}
|
||||
|
||||
logger.info('connecting user : ${user.id}');
|
||||
logger.info('setting user : ${user.id}');
|
||||
|
||||
await _tokenManager.setTokenOrProvider(
|
||||
user.id,
|
||||
@@ -279,17 +310,21 @@ class StreamChatClient {
|
||||
final ownUser = OwnUser.fromUser(user);
|
||||
state.user = ownUser;
|
||||
|
||||
if (!connectWebSocket) {
|
||||
return ownUser;
|
||||
}
|
||||
|
||||
try {
|
||||
if (_originalChatPersistenceClient != null) {
|
||||
_chatPersistenceClient = _originalChatPersistenceClient;
|
||||
await _chatPersistenceClient!.connect(ownUser.id);
|
||||
}
|
||||
final event = await openConnection();
|
||||
return event;
|
||||
final res = await openConnection();
|
||||
return res;
|
||||
} catch (e, stk) {
|
||||
if (e is StreamWebSocketError && e.isRetriable) {
|
||||
final event = await _chatPersistenceClient?.getConnectionInfo();
|
||||
if (event != null) return event;
|
||||
if (event != null) return event.me?.merge(ownUser) ?? ownUser;
|
||||
}
|
||||
logger.severe('error connecting user : ${ownUser.id}', e, stk);
|
||||
rethrow;
|
||||
@@ -297,7 +332,7 @@ class StreamChatClient {
|
||||
}
|
||||
|
||||
/// Creates a new WebSocket connection with the current user.
|
||||
Future<Event> openConnection() async {
|
||||
Future<OwnUser> openConnection() async {
|
||||
assert(
|
||||
state.user != null,
|
||||
'User is not set on client, '
|
||||
@@ -327,7 +362,8 @@ class StreamChatClient {
|
||||
_ws.connectionStatusStream.skip(1).listen(_connectionStatusHandler);
|
||||
|
||||
try {
|
||||
return await _ws.connect(user);
|
||||
final event = await _ws.connect(user);
|
||||
return event.me?.merge(user) ?? user;
|
||||
} catch (e, stk) {
|
||||
logger.severe('error connecting ws', e, stk);
|
||||
rethrow;
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:stream_chat/src/core/models/device.dart';
|
||||
import 'package:stream_chat/src/core/models/mute.dart';
|
||||
import 'package:stream_chat/src/core/models/user.dart';
|
||||
import 'package:stream_chat/src/core/util/serializer.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
part 'own_user.g.dart';
|
||||
|
||||
@@ -25,6 +26,7 @@ class OwnUser extends User {
|
||||
bool online = false,
|
||||
Map<String, Object?> extraData = const {},
|
||||
bool banned = false,
|
||||
List<String> teams = const [],
|
||||
}) : super(
|
||||
id: id,
|
||||
role: role,
|
||||
@@ -34,6 +36,7 @@ class OwnUser extends User {
|
||||
online: online,
|
||||
extraData: extraData,
|
||||
banned: banned,
|
||||
teams: teams,
|
||||
);
|
||||
|
||||
/// Create a new instance from a json
|
||||
@@ -50,8 +53,69 @@ class OwnUser extends User {
|
||||
online: user.online,
|
||||
banned: user.banned,
|
||||
extraData: user.extraData,
|
||||
teams: user.teams,
|
||||
);
|
||||
|
||||
/// Creates a copy of [OwnUser] with specified attributes overridden.
|
||||
@override
|
||||
OwnUser copyWith({
|
||||
String? id,
|
||||
String? role,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastActive,
|
||||
bool? online,
|
||||
Map<String, Object?>? extraData,
|
||||
bool? banned,
|
||||
List<String>? teams,
|
||||
List<Mute>? channelMutes,
|
||||
List<Device>? devices,
|
||||
List<Mute>? mutes,
|
||||
int? totalUnreadCount,
|
||||
int? unreadChannels,
|
||||
}) =>
|
||||
OwnUser(
|
||||
id: id ?? this.id,
|
||||
banned: banned ?? this.banned,
|
||||
role: role ?? this.role,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
lastActive: lastActive ?? this.lastActive,
|
||||
online: online ?? this.online,
|
||||
extraData: extraData ?? this.extraData,
|
||||
teams: teams ?? this.teams,
|
||||
channelMutes: channelMutes ?? this.channelMutes,
|
||||
devices: devices ?? this.devices,
|
||||
mutes: mutes ?? this.mutes,
|
||||
totalUnreadCount: totalUnreadCount ?? this.totalUnreadCount,
|
||||
unreadChannels: unreadChannels ?? this.unreadChannels,
|
||||
);
|
||||
|
||||
/// Returns a new [OwnUser] that is a combination of this ownUser
|
||||
/// and the given [other] ownUser.
|
||||
OwnUser merge(OwnUser? other) {
|
||||
if (other == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return copyWith(
|
||||
banned: other.banned,
|
||||
channelMutes: other.channelMutes,
|
||||
createdAt: other.createdAt,
|
||||
devices: other.devices,
|
||||
extraData: other.extraData,
|
||||
id: other.id,
|
||||
lastActive: other.lastActive,
|
||||
mutes: other.mutes,
|
||||
online: other.online,
|
||||
role: other.role,
|
||||
teams: other.teams,
|
||||
totalUnreadCount: other.totalUnreadCount,
|
||||
unreadChannels: other.unreadChannels,
|
||||
updatedAt: other.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
/// List of user devices
|
||||
@JsonKey(includeIfNull: false, defaultValue: <Device>[])
|
||||
final List<Device> devices;
|
||||
|
||||
@@ -47,9 +47,10 @@ class User extends Equatable {
|
||||
|
||||
/// User role
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
defaultValue: <String>[])
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
defaultValue: <String>[],
|
||||
)
|
||||
final List<String> teams;
|
||||
|
||||
/// Date of user creation
|
||||
|
||||
Reference in New Issue
Block a user