fixed tests, null errors

This commit is contained in:
Deven Joshi
2021-04-12 18:44:30 +05:30
parent 686dcf27e6
commit 9ec4c83cfc
18 changed files with 124 additions and 106 deletions
+46 -47
View File
@@ -78,63 +78,63 @@ class Channel {
/// Channel configuration as a stream /// Channel configuration as a stream
Stream<ChannelConfig?>? get configStream => Stream<ChannelConfig?>? get configStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.config); state?.channelStateStream.map((cs) => cs!.channel?.config);
/// Channel user creator /// Channel user creator
User? get createdBy => state?._channelState?.channel?.createdBy; User? get createdBy => state?._channelState?.channel?.createdBy;
/// Channel user creator as a stream /// Channel user creator as a stream
Stream<User?>? get createdByStream => Stream<User?>? get createdByStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.createdBy); state?.channelStateStream.map((cs) => cs!.channel?.createdBy);
/// Channel frozen status /// Channel frozen status
bool? get frozen => state?._channelState?.channel?.frozen; bool? get frozen => state?._channelState?.channel?.frozen;
/// Channel frozen status as a stream /// Channel frozen status as a stream
Stream<bool?>? get frozenStream => Stream<bool?>? get frozenStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.frozen); state?.channelStateStream.map((cs) => cs!.channel?.frozen);
/// Channel creation date /// Channel creation date
DateTime? get createdAt => state?._channelState?.channel?.createdAt; DateTime? get createdAt => state?._channelState?.channel?.createdAt;
/// Channel creation date as a stream /// Channel creation date as a stream
Stream<DateTime?>? get createdAtStream => Stream<DateTime?>? get createdAtStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.createdAt); state?.channelStateStream.map((cs) => cs!.channel?.createdAt);
/// Channel last message date /// Channel last message date
DateTime? get lastMessageAt => state?._channelState?.channel?.lastMessageAt; DateTime? get lastMessageAt => state?._channelState?.channel?.lastMessageAt;
/// Channel last message date as a stream /// Channel last message date as a stream
Stream<DateTime?>? get lastMessageAtStream => Stream<DateTime?>? get lastMessageAtStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.lastMessageAt); state?.channelStateStream.map((cs) => cs!.channel?.lastMessageAt);
/// Channel updated date /// Channel updated date
DateTime? get updatedAt => state?._channelState?.channel?.updatedAt; DateTime? get updatedAt => state?._channelState?.channel?.updatedAt;
/// Channel updated date as a stream /// Channel updated date as a stream
Stream<DateTime?>? get updatedAtStream => Stream<DateTime?>? get updatedAtStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.updatedAt); state?.channelStateStream.map((cs) => cs!.channel?.updatedAt);
/// Channel deletion date /// Channel deletion date
DateTime? get deletedAt => state?._channelState?.channel?.deletedAt; DateTime? get deletedAt => state?._channelState?.channel?.deletedAt;
/// Channel deletion date as a stream /// Channel deletion date as a stream
Stream<DateTime?>? get deletedAtStream => Stream<DateTime?>? get deletedAtStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.deletedAt); state?.channelStateStream.map((cs) => cs!.channel?.deletedAt);
/// Channel member count /// Channel member count
int? get memberCount => state?._channelState?.channel?.memberCount; int? get memberCount => state?._channelState?.channel?.memberCount;
/// Channel member count as a stream /// Channel member count as a stream
Stream<int?>? get memberCountStream => Stream<int?>? get memberCountStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.memberCount); state?.channelStateStream.map((cs) => cs!.channel?.memberCount);
/// Channel id /// Channel id
String? get id => state?._channelState?.channel?.id ?? _id; String? get id => state?._channelState?.channel?.id ?? _id;
/// Channel id as a stream /// Channel id as a stream
Stream<String?>? get idStream => Stream<String?>? get idStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.id ?? _id); state?.channelStateStream.map((cs) => cs!.channel?.id ?? _id);
/// Channel cid /// Channel cid
String? get cid => state?._channelState?.channel?.cid ?? _cid; String? get cid => state?._channelState?.channel?.cid ?? _cid;
@@ -144,7 +144,7 @@ class Channel {
/// Channel cid as a stream /// Channel cid as a stream
Stream<String?>? get cidStream => Stream<String?>? get cidStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.cid ?? _cid); state?.channelStateStream.map((cs) => cs!.channel?.cid ?? _cid);
/// Channel extra data /// Channel extra data
Map<String, dynamic>? get extraData => Map<String, dynamic>? get extraData =>
@@ -152,7 +152,7 @@ class Channel {
/// Channel extra data as a stream /// Channel extra data as a stream
Stream<Map<String, dynamic>?>? get extraDataStream => Stream<Map<String, dynamic>?>? get extraDataStream =>
state?.channelStateStream?.map((cs) => cs!.channel?.extraData); state?.channelStateStream.map((cs) => cs!.channel?.extraData);
/// The main Stream chat client /// The main Stream chat client
StreamChatClient get client => _client; StreamChatClient get client => _client;
@@ -284,7 +284,7 @@ class Channel {
it.copyWith(uploadState: UploadState.failed(error: e.toString())), it.copyWith(uploadState: UploadState.failed(error: e.toString())),
); );
}).whenComplete(() { }).whenComplete(() {
throttledUpdateAttachment?.cancel(); throttledUpdateAttachment.cancel();
_cancelableAttachmentUploadRequest.remove(it.id); _cancelableAttachmentUploadRequest.remove(it.id);
}); });
})).whenComplete(() { })).whenComplete(() {
@@ -297,7 +297,7 @@ class Channel {
/// Send a [message] to this channel. /// Send a [message] to this channel.
/// Waits for a [_messageAttachmentsUploadCompleter] to complete /// Waits for a [_messageAttachmentsUploadCompleter] to complete
/// before actually sending the message. /// before actually sending the message.
Future<SendMessageResponse> sendMessage(Message message) async { Future<SendMessageResponse?> sendMessage(Message message) async {
// Cancelling previous completer in case it's called again in the process // Cancelling previous completer in case it's called again in the process
// Eg. Updating the message while the previous call is in progress. // Eg. Updating the message while the previous call is in progress.
_messageAttachmentsUploadCompleter _messageAttachmentsUploadCompleter
@@ -305,7 +305,7 @@ class Channel {
?.completeError('Message Cancelled'); ?.completeError('Message Cancelled');
final quotedMessage = state?.messages?.firstWhereOrNull( final quotedMessage = state?.messages?.firstWhereOrNull(
(m) => m.id == message?.quotedMessageId, (m) => m.id == message.quotedMessageId,
); );
// ignore: parameter_assignments // ignore: parameter_assignments
message = message.copyWith( message = message.copyWith(
@@ -318,7 +318,7 @@ class Channel {
if (it.uploadState.isSuccess) return it; if (it.uploadState.isSuccess) return it;
return it.copyWith(uploadState: const UploadState.preparing()); return it.copyWith(uploadState: const UploadState.preparing());
}, },
)?.toList(), ).toList(),
); );
if (message.parentId != null && message.id == null) { if (message.parentId != null && message.id == null) {
@@ -348,9 +348,8 @@ class Channel {
message = await attachmentsUploadCompleter.future; message = await attachmentsUploadCompleter.future;
} }
final response = await (_client.sendMessage(message, id, type) final response = await (_client.sendMessage(message, id, type));
as FutureOr<SendMessageResponse>); state?.addMessage(response!.message!);
state?.addMessage(response.message!);
return response; return response;
} catch (error) { } catch (error) {
if (error is DioError && error.type != DioErrorType.response) { if (error is DioError && error.type != DioErrorType.response) {
@@ -379,7 +378,7 @@ class Channel {
if (it.uploadState.isSuccess) return it; if (it.uploadState.isSuccess) return it;
return it.copyWith(uploadState: const UploadState.preparing()); return it.copyWith(uploadState: const UploadState.preparing());
}, },
)?.toList(), ).toList(),
); );
state?.addMessage(message); state?.addMessage(message);
@@ -596,7 +595,7 @@ class Channel {
..removeWhere((it) => it.userId != user!.id); ..removeWhere((it) => it.userId != user!.id);
final newMessage = message.copyWith( final newMessage = message.copyWith(
reactionCounts: {...message?.reactionCounts ?? <String, int>{}} reactionCounts: {...message.reactionCounts ?? <String, int>{}}
..update(type, (value) { ..update(type, (value) {
if (enforceUnique) return value; if (enforceUnique) return value;
return value + 1; return value + 1;
@@ -660,7 +659,7 @@ class Channel {
r.type == reaction.type && r.type == reaction.type &&
r.messageId == reaction.messageId); r.messageId == reaction.messageId);
final ownReactions = [...latestReactions ?? <Reaction>[]] final ownReactions = [...latestReactions]
..removeWhere((it) => it.userId != user!.id); ..removeWhere((it) => it.userId != user!.id);
final newMessage = message.copyWith( final newMessage = message.copyWith(
@@ -867,7 +866,7 @@ class Channel {
'$_channelURL/stop-watching', '$_channelURL/stop-watching',
data: {}, data: {},
); );
return _client.decode(response?.data, EmptyResponse.fromJson); return _client.decode(response.data, EmptyResponse.fromJson);
} }
/// List the message replies for a parent message /// List the message replies for a parent message
@@ -878,10 +877,10 @@ class Channel {
PaginationParams options, { PaginationParams options, {
bool preferOffline = false, bool preferOffline = false,
}) async { }) async {
final cachedReplies = (await _client.chatPersistenceClient?.getReplies( final cachedReplies = await _client.chatPersistenceClient?.getReplies(
parentId, parentId,
options: options, options: options,
))!; );
if (cachedReplies != null && cachedReplies.isNotEmpty) { if (cachedReplies != null && cachedReplies.isNotEmpty) {
state?.updateThreadInfo(parentId, cachedReplies); state?.updateThreadInfo(parentId, cachedReplies);
if (preferOffline) { if (preferOffline) {
@@ -1049,7 +1048,7 @@ class Channel {
if (id != null) { if (id != null) {
payload['id'] = id; payload['id'] = id;
} else if (state?.members?.isNotEmpty == true) { } else if (state?.members.isNotEmpty == true) {
payload['members'] = state!.members; payload['members'] = state!.members;
} }
@@ -1222,7 +1221,7 @@ class ChannelClientState {
ChannelState channelState, ChannelState channelState,
//ignore: unnecessary_parenthesis //ignore: unnecessary_parenthesis
) : _debouncedUpdatePersistenceChannelState = ((ChannelState state) => ) : _debouncedUpdatePersistenceChannelState = ((ChannelState state) =>
_channel?._client?.chatPersistenceClient _channel._client.chatPersistenceClient
?.updateChannelState(state)) ?.updateChannelState(state))
.debounced(const Duration(seconds: 1)) { .debounced(const Duration(seconds: 1)) {
retryQueue = RetryQueue( retryQueue = RetryQueue(
@@ -1264,12 +1263,12 @@ class ChannelClientState {
_channel._client.chatPersistenceClient _channel._client.chatPersistenceClient
?.getChannelThreads(_channel.cid) ?.getChannelThreads(_channel.cid)
?.then((threads) { .then((threads) {
_threads = threads; _threads = threads;
})?.then((_) { }).then((_) {
_channel._client.chatPersistenceClient _channel._client.chatPersistenceClient
?.getChannelStateByCid(_channel.cid) ?.getChannelStateByCid(_channel.cid)
?.then((state) { .then((state) {
// Replacing the persistence state members with the latest // Replacing the persistence state members with the latest
// `channelState.members` as they may have changes over the time. // `channelState.members` as they may have changes over the time.
updateChannelState(state.copyWith(members: channelState.members)); updateChannelState(state.copyWith(members: channelState.members));
@@ -1309,8 +1308,8 @@ class ChannelClientState {
return expiration.isBefore(DateTime.now()); return expiration.isBefore(DateTime.now());
}) == }) ==
true) true)
?.map((e) => e.id) .map((e) => e.id)
?.toList(); .toList();
if (expiredAttachmentMessagesId?.isNotEmpty == true) { if (expiredAttachmentMessagesId?.isNotEmpty == true) {
_channel.getMessagesById(expiredAttachmentMessagesId!); _channel.getMessagesById(expiredAttachmentMessagesId!);
_updatedMessagesIds.addAll(expiredAttachmentMessagesId); _updatedMessagesIds.addAll(expiredAttachmentMessagesId);
@@ -1560,7 +1559,7 @@ class ChannelClientState {
/// Channel members list /// Channel members list
List<Member> get members => _channelState!.members! List<Member> get members => _channelState!.members!
.map((e) => e!.copyWith(user: _channel.client.state!.users![e.user!.id!])) .map((e) => e!.copyWith(user: _channel.client.state!.users[e.user!.id!]))
.toList(); .toList();
/// Channel members list as a stream /// Channel members list as a stream
@@ -1581,7 +1580,7 @@ class ChannelClientState {
/// Channel watchers list /// Channel watchers list
List<User> get watchers => _channelState!.watchers! List<User> get watchers => _channelState!.watchers!
.map((e) => _channel.client.state!.users![e.id!] ?? e) .map((e) => _channel.client.state!.users[e.id!] ?? e)
.toList(); .toList();
/// Channel watchers list as a stream /// Channel watchers list as a stream
@@ -1628,7 +1627,7 @@ class ChannelClientState {
...newThreads[parentId] ...newThreads[parentId]
?.where((newMessage) => ?.where((newMessage) =>
!messages!.any((m) => m.id == newMessage.id)) !messages!.any((m) => m.id == newMessage.id))
?.toList() ?? .toList() ??
[], [],
...messages!, ...messages!,
]; ];
@@ -1654,39 +1653,39 @@ class ChannelClientState {
/// Update channelState with updated information /// Update channelState with updated information
void updateChannelState(ChannelState updatedState) { void updateChannelState(ChannelState updatedState) {
final newMessages = <Message>[ final newMessages = <Message>[
...updatedState?.messages ?? [], ...updatedState.messages ?? [],
..._channelState?.messages ..._channelState?.messages
?.where((m) => ?.where((m) =>
updatedState.messages updatedState.messages
?.any((newMessage) => newMessage.id == m.id) != ?.any((newMessage) => newMessage.id == m.id) !=
true) true)
?.toList() ?? .toList() ??
[], [],
]..sort(_sortByCreatedAt as int Function(Message, Message)?); ]..sort(_sortByCreatedAt as int Function(Message, Message)?);
final newWatchers = <User>[ final newWatchers = <User>[
...updatedState?.watchers ?? [], ...updatedState.watchers ?? [],
..._channelState?.watchers ..._channelState?.watchers
?.where((w) => ?.where((w) =>
updatedState.watchers updatedState.watchers
?.any((newWatcher) => newWatcher.id == w.id) != ?.any((newWatcher) => newWatcher.id == w.id) !=
true) true)
?.toList() ?? .toList() ??
[], [],
]; ];
final newMembers = <Member?>[ final newMembers = <Member?>[
...updatedState?.members ?? [], ...updatedState.members ?? [],
]; ];
final newReads = <Read>[ final newReads = <Read>[
...updatedState?.read ?? [], ...updatedState.read ?? [],
..._channelState?.read ..._channelState?.read
?.where((r) => ?.where((r) =>
updatedState.read updatedState.read
?.any((newRead) => newRead.user!.id == r.user!.id) != ?.any((newRead) => newRead.user!.id == r.user!.id) !=
true) true)
?.toList() ?? .toList() ??
[], [],
]; ];
@@ -1730,12 +1729,12 @@ class ChannelClientState {
set _channelState(ChannelState? v) { set _channelState(ChannelState? v) {
_channelStateController.add(v); _channelStateController.add(v);
_debouncedUpdatePersistenceChannelState?.call([v]); _debouncedUpdatePersistenceChannelState.call([v]);
} }
/// The channel threads related to this channel /// The channel threads related to this channel
Map<String, List<Message>>? get threads => Map<String, List<Message>>? get threads => _threadsController.value
_threadsController.value as Map<String, List<Message>>?; ?.map((key, value) => MapEntry(key ?? '', value ?? []));
/// The channel threads related to this channel as a stream /// The channel threads related to this channel as a stream
Stream<Map<String?, List<Message>?>> get threadsStream => Stream<Map<String?, List<Message>?>> get threadsStream =>
@@ -1793,7 +1792,7 @@ class ChannelClientState {
.on() .on()
.where((event) => .where((event) =>
event.user != null && event.user != null &&
members?.any((m) => m.userId == event.user!.id) == true) members.any((m) => m.userId == event.user!.id) == true)
.listen( .listen(
(event) { (event) {
final newMembers = List<Member>.from(members); final newMembers = List<Member>.from(members);
@@ -1841,7 +1840,7 @@ class ChannelClientState {
final now = DateTime.now(); final now = DateTime.now();
var expiredMessages = channelState!.pinnedMessages var expiredMessages = channelState!.pinnedMessages
?.where((m) => m.pinExpires?.isBefore(now) == true) ?.where((m) => m.pinExpires?.isBefore(now) == true)
?.toList() ?? .toList() ??
[]; [];
if (expiredMessages.isNotEmpty) { if (expiredMessages.isNotEmpty) {
expiredMessages = expiredMessages expiredMessages = expiredMessages
@@ -1876,7 +1875,7 @@ class ChannelClientState {
/// Call this method to dispose this object /// Call this method to dispose this object
void dispose() { void dispose() {
_debouncedUpdatePersistenceChannelState?.cancel(); _debouncedUpdatePersistenceChannelState.cancel();
_unreadCountController.close(); _unreadCountController.close();
retryQueue!.dispose(); retryQueue!.dispose();
_subscriptions.forEach((s) => s.cancel()); _subscriptions.forEach((s) => s.cancel());
@@ -20,7 +20,7 @@ QueryChannelsResponse _$QueryChannelsResponseFromJson(Map json) {
return QueryChannelsResponse() return QueryChannelsResponse()
..duration = json['duration'] as String? ..duration = json['duration'] as String?
..channels = (json['channels'] as List<dynamic>?) ..channels = (json['channels'] as List<dynamic>?)
?.map((e) => ChannelState.fromJson(e as Map)) ?.map((e) => ChannelState.fromJson(e as Map<String, dynamic>))
.toList(); .toList();
} }
@@ -169,7 +169,7 @@ SearchMessagesResponse _$SearchMessagesResponseFromJson(Map json) {
return SearchMessagesResponse() return SearchMessagesResponse()
..duration = json['duration'] as String? ..duration = json['duration'] as String?
..results = (json['results'] as List<dynamic>?) ..results = (json['results'] as List<dynamic>?)
?.map((e) => GetMessageResponse.fromJson(e as Map)) ?.map((e) => GetMessageResponse.fromJson(e as Map<String, dynamic>))
.toList(); .toList();
} }
@@ -1,4 +1,3 @@
import 'package:meta/meta.dart';
import 'package:stream_chat/src/client.dart'; import 'package:stream_chat/src/client.dart';
import 'package:stream_chat/src/exceptions.dart'; import 'package:stream_chat/src/exceptions.dart';
@@ -2,7 +2,6 @@ import 'dart:async';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:stream_chat/src/api/channel.dart'; import 'package:stream_chat/src/api/channel.dart';
import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/api/retry_policy.dart';
import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/event_type.dart';
@@ -153,9 +153,7 @@ class WebSocket {
onError: (error, stacktrace) { onError: (error, stacktrace) {
_onConnectionError(error, stacktrace); _onConnectionError(error, stacktrace);
}, },
onDone: () { onDone: _onDone,
_onDone();
},
); );
return _connectionCompleter.future; return _connectionCompleter.future;
} }
@@ -70,7 +70,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
ProgressCallback? onSendProgress, ProgressCallback? onSendProgress,
CancelToken? cancelToken, CancelToken? cancelToken,
}) async { }) async {
final filename = file!.path?.split('/')?.last ?? file.name; final filename = file!.path?.split('/').last ?? file.name;
final mimeType = filename.mimeType; final mimeType = filename.mimeType;
MultipartFile? multiPartFile; MultipartFile? multiPartFile;
@@ -107,7 +107,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
ProgressCallback? onSendProgress, ProgressCallback? onSendProgress,
CancelToken? cancelToken, CancelToken? cancelToken,
}) async { }) async {
final filename = file!.path?.split('/')?.last ?? file.name; final filename = file!.path?.split('/').last ?? file.name;
final mimeType = filename.mimeType; final mimeType = filename.mimeType;
MultipartFile? multiPartFile; MultipartFile? multiPartFile;
+22 -13
View File
@@ -34,7 +34,7 @@ import 'package:uuid/uuid.dart';
typedef LogHandlerFunction = void Function(LogRecord record); typedef LogHandlerFunction = void Function(LogRecord record);
/// Used for decoding [Map] data to a generic type `T`. /// Used for decoding [Map] data to a generic type `T`.
typedef DecoderFunction<T> = T Function(Map<String, dynamic>?); typedef DecoderFunction<T> = T Function(Map<String, dynamic>);
/// A function which can be used to request a Stream Chat API token from your /// A function which can be used to request a Stream Chat API token from your
/// own backend server. Function requires a single [userId]. /// own backend server. Function requires a single [userId].
@@ -268,9 +268,8 @@ class StreamChatClient {
var stringData = options.data.toString(); var stringData = options.data.toString();
if (options.data is FormData) { if (options.data is FormData) {
final multiPart = (options.data as FormData).files[0]?.value; final multiPart = (options.data as FormData).files[0].value;
stringData = stringData = '${multiPart.filename} - ${multiPart.contentType}';
'${multiPart?.filename} - ${multiPart?.contentType}';
} }
logger.info(''' logger.info('''
@@ -408,7 +407,7 @@ class StreamChatClient {
/// Connects the current user, this triggers a connection to the API. /// Connects the current user, this triggers a connection to the API.
/// It returns a [Future] that resolves when the connection is setup. /// It returns a [Future] that resolves when the connection is setup.
Future<Event> connectUser(User user, String? token) async { Future<Event> connectUser(User? user, String? token) async {
if (_connectCompleter != null && !_connectCompleter!.isCompleted) { if (_connectCompleter != null && !_connectCompleter!.isCompleted) {
logger.warning('Already connecting'); logger.warning('Already connecting');
throw Exception('Already connecting'); throw Exception('Already connecting');
@@ -417,6 +416,14 @@ class StreamChatClient {
_connectCompleter = Completer(); _connectCompleter = Completer();
logger.info('connect user'); logger.info('connect user');
if (user == null) {
final e = Error();
_connectCompleter!
.completeError(e, StackTrace.fromString('No user provided.'));
throw e;
}
state!.user = OwnUser.fromJson(user.toJson()); state!.user = OwnUser.fromJson(user.toJson());
this.token = token; this.token = token;
_anonymous = false; _anonymous = false;
@@ -638,7 +645,7 @@ class StreamChatClient {
bool waitForConnect = true, bool waitForConnect = true,
}) async* { }) async* {
final hash = base64.encode(utf8.encode( final hash = base64.encode(utf8.encode(
'$filter${_asMap(sort)}$options${paginationParams?.toJson()}' '$filter${_asMap(sort)}$options${paginationParams.toJson()}'
'$messageLimit', '$messageLimit',
)); ));
@@ -731,7 +738,7 @@ class StreamChatClient {
QueryChannelsResponse.fromJson, QueryChannelsResponse.fromJson,
)!; )!;
if ((res.channels ?? []).isEmpty && (paginationParams?.offset ?? 0) == 0) { if ((res.channels ?? []).isEmpty && (paginationParams.offset) == 0) {
logger.warning( logger.warning(
''' '''
We could not find any channel for this query. We could not find any channel for this query.
@@ -758,7 +765,7 @@ class StreamChatClient {
filter, filter,
channels.map((c) => c.channel!.cid).toList(), channels.map((c) => c.channel!.cid).toList(),
clearQueryCache: clearQueryCache:
paginationParams?.offset == null || paginationParams.offset == 0, paginationParams.offset == null || paginationParams.offset == 0,
); );
state!.channels = updateData.key; state!.channels = updateData.key;
@@ -976,8 +983,9 @@ class StreamChatClient {
.then((res) => decode<ConnectGuestUserResponse>( .then((res) => decode<ConnectGuestUserResponse>(
res.data, ConnectGuestUserResponse.fromJson)) res.data, ConnectGuestUserResponse.fromJson))
.whenComplete(() => _anonymous = false); .whenComplete(() => _anonymous = false);
return connectUser( return connectUser(
(response?.user)!, response?.user,
response?.accessToken, response?.accessToken,
); );
} }
@@ -1008,7 +1016,7 @@ class StreamChatClient {
Future<void> _disconnect() async { Future<void> _disconnect() async {
logger.info('Client disconnecting'); logger.info('Client disconnecting');
await _ws?.disconnect(); await _ws.disconnect();
await _connectionStatusSubscription?.cancel(); await _connectionStatusSubscription?.cancel();
} }
@@ -1427,7 +1435,7 @@ class ClientState {
/// Used internally for optimistic update of unread count /// Used internally for optimistic update of unread count
set totalUnreadCount(int? unreadCount) { set totalUnreadCount(int? unreadCount) {
_totalUnreadCountController?.add(unreadCount ?? 0); _totalUnreadCountController.add(unreadCount ?? 0);
} }
void _listenChannelHidden() { void _listenChannelHidden() {
@@ -1473,7 +1481,7 @@ class ClientState {
void _updateUsers(List<User?> userList) { void _updateUsers(List<User?> userList) {
final newUsers = { final newUsers = {
...users ?? {}, ...users,
for (var user in userList) user!.id: user, for (var user in userList) user!.id: user,
}; };
_usersController.add(newUsers); _usersController.add(newUsers);
@@ -1488,7 +1496,8 @@ class ClientState {
Stream<OwnUser?> get userStream => _userController.stream; Stream<OwnUser?> get userStream => _userController.stream;
/// The current user /// The current user
Map<String, User>? get users => _usersController.value as Map<String, User>?; Map<String?, User?> get users =>
_usersController.value as Map<String?, User?>;
/// The current user as a stream /// The current user as a stream
Stream<Map<String?, User?>> get usersStream => _usersController.stream; Stream<Map<String?, User?>> get usersStream => _usersController.stream;
@@ -213,7 +213,7 @@ abstract class ChatPersistenceClient {
if (m.ownReactions != null) if (m.ownReactions != null)
...m.ownReactions!.map((r) => r.user), ...m.ownReactions!.map((r) => r.user),
]) ])
?.expand((v) => v), .expand((v) => v),
if (cs.read != null) ...cs.read!.map((r) => r.user), if (cs.read != null) ...cs.read!.map((r) => r.user),
if (cs.members != null) ...cs.members!.map((m) => m!.user), if (cs.members != null) ...cs.members!.map((m) => m!.user),
]) ])
@@ -124,7 +124,7 @@ class Debounce {
Duration? maxWait, Duration? maxWait,
}) : _leading = leading, }) : _leading = leading,
_trailing = trailing, _trailing = trailing,
_wait = wait?.inMilliseconds ?? 0, _wait = wait.inMilliseconds,
_maxing = maxWait != null { _maxing = maxWait != null {
if (_maxing) { if (_maxing) {
_maxWait = math.max(maxWait!.inMilliseconds, _wait); _maxWait = math.max(maxWait!.inMilliseconds, _wait);
@@ -87,7 +87,7 @@ class AttachmentFile {
final int? size; final int? size;
/// File extension for this file. /// File extension for this file.
String? get extension => name?.split('.')?.last; String? get extension => name?.split('.').last;
/// Serialize to json /// Serialize to json
Map<String, dynamic> toJson() => _$AttachmentFileToJson(this); Map<String, dynamic> toJson() => _$AttachmentFileToJson(this);
@@ -43,8 +43,8 @@ class ChannelState {
final List<Read>? read; final List<Read>? read;
/// Create a new instance from a json /// Create a new instance from a json
static ChannelState fromJson(Map<String, dynamic>? json) => static ChannelState fromJson(Map<String, dynamic> json) =>
_$ChannelStateFromJson(json!); _$ChannelStateFromJson(json);
/// Serialize to json /// Serialize to json
Map<String, dynamic> toJson() => _$ChannelStateToJson(this); Map<String, dynamic> toJson() => _$ChannelStateToJson(this);
@@ -11,7 +11,7 @@ class Serialization {
/// List of users to list of userIds /// List of users to list of userIds
static List<String?>? userIds(List<User>? users) => static List<String?>? userIds(List<User>? users) =>
users?.map((u) => u.id)?.toList(); users?.map((u) => u.id).toList();
/// Takes unknown json keys and puts them in the `extra_data` key /// Takes unknown json keys and puts them in the `extra_data` key
static Map<String, dynamic>? moveToExtraDataFromRoot( static Map<String, dynamic>? moveToExtraDataFromRoot(
+1 -1
View File
@@ -23,7 +23,7 @@ dependencies:
web_socket_channel: ^2.0.0 web_socket_channel: ^2.0.0
dev_dependencies: dev_dependencies:
build_runner: ^1.10.0 build_runner: ^1.12.2
freezed: ^0.14.1+2 freezed: ^0.14.1+2
json_serializable: ^4.1.0 json_serializable: ^4.1.0
mocktail: ^0.1.1 mocktail: ^0.1.1
@@ -50,7 +50,7 @@ void main() {
), ),
); );
await channelClient?.sendMessage(message); await channelClient.sendMessage(message);
verify(() => verify(() =>
mockDio.post<String>('/channels/messaging/testid/message', data: { mockDio.post<String>('/channels/messaging/testid/message', data: {
@@ -80,7 +80,7 @@ void main() {
statusCode: 200, statusCode: 200,
requestOptions: FakeRequestOptions(), requestOptions: FakeRequestOptions(),
)); ));
await channelClient?.watch(); await channelClient.watch();
when( when(
() => mockDio.post<String>( () => mockDio.post<String>(
@@ -95,7 +95,7 @@ void main() {
), ),
); );
await channelClient?.markRead(); await channelClient.markRead();
verify(() => mockDio.post<String>('/channels/messaging/testid/read', verify(() => mockDio.post<String>('/channels/messaging/testid/read',
data: {})).called(1); data: {})).called(1);
@@ -124,7 +124,7 @@ void main() {
), ),
); );
await channelClient?.getReplies('messageid', pagination); await channelClient.getReplies('messageid', pagination);
verify(() => mockDio.get<String>('/messages/messageid/replies', verify(() => mockDio.get<String>('/messages/messageid/replies',
queryParameters: pagination.toJson())).called(1); queryParameters: pagination.toJson())).called(1);
@@ -141,7 +141,7 @@ void main() {
httpClient: mockDio, httpClient: mockDio,
tokenProvider: (_) async => '', tokenProvider: (_) async => '',
); );
Channel channelClient = client.channel('messaging', id: 'testid'); final channelClient = client.channel('messaging', id: 'testid');
when(() => mockDio.post<String>( when(() => mockDio.post<String>(
any(), any(),
@@ -566,9 +566,7 @@ void main() {
tokenProvider: (_) async => '', tokenProvider: (_) async => '',
); );
if (client != null) { client.state?.user = OwnUser(id: 'test-id');
client.state?.user = OwnUser(id: 'test-id');
}
final channelClient = client.channel('messaging', id: 'testid'); final channelClient = client.channel('messaging', id: 'testid');
const reactionType = 'test'; const reactionType = 'test';
@@ -623,9 +621,7 @@ void main() {
tokenProvider: (_) async => '', tokenProvider: (_) async => '',
); );
if (client != null) { client.state?.user = OwnUser(id: 'test-id');
client.state?.user = OwnUser(id: 'test-id');
}
final channelClient = client.channel('messaging', id: 'testid'); final channelClient = client.channel('messaging', id: 'testid');
@@ -12,7 +12,9 @@ void main() {
test('PaginationParams', () { test('PaginationParams', () {
const option = PaginationParams(); const option = PaginationParams();
final j = option.toJson(); final j = option.toJson();
expect(j, {'limit': 10, 'offset': 0}); expect(j, containsPair('limit', 10));
expect(j, containsPair('offset', 0));
expect(j, contains('hash_code'));
}); });
}); });
} }
@@ -12,7 +12,8 @@ import 'package:stream_chat/stream_chat.dart';
void main() { void main() {
group('src/api/responses', () { group('src/api/responses', () {
test('QueryChannelsResponse', () { test('QueryChannelsResponse', () {
const jsonExample = r'''{ const jsonExample = r'''
{
"channels": [ "channels": [
{ {
"channel": { "channel": {
@@ -3432,7 +3433,8 @@ void main() {
}); });
test('SendReactionResponse', () { test('SendReactionResponse', () {
const jsonExample = r'''{"message": { const jsonExample = r'''
{"message": {
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3481,7 +3483,8 @@ void main() {
}); });
test('UpdateUsersResponse', () { test('UpdateUsersResponse', () {
const jsonExample = '''{"users": {"bbb19d9a-ee50-45bc-84e5-0584e79d0c9e":{ const jsonExample = '''
{"users": {"bbb19d9a-ee50-45bc-84e5-0584e79d0c9e":{
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e", "id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e",
"role": "user", "role": "user",
"created_at": "2020-01-28T22:17:30.826259Z", "created_at": "2020-01-28T22:17:30.826259Z",
@@ -3505,7 +3508,8 @@ void main() {
}); });
test('GetMessagesByIdResponse', () { test('GetMessagesByIdResponse', () {
const jsonExample = r'''{"messages":[{ const jsonExample = r'''
{"messages":[{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3536,7 +3540,8 @@ void main() {
}); });
test('SendActionResponse', () { test('SendActionResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3566,7 +3571,8 @@ void main() {
}); });
test('UpdateMessageResponse', () { test('UpdateMessageResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3596,7 +3602,8 @@ void main() {
}); });
test('SendMessageResponse', () { test('SendMessageResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3626,7 +3633,8 @@ void main() {
}); });
test('GetMessageResponse', () { test('GetMessageResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3656,7 +3664,8 @@ void main() {
}); });
test('UpdateChannelResponse', () { test('UpdateChannelResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3769,7 +3778,8 @@ void main() {
}); });
test('InviteMembersResponse', () { test('InviteMembersResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3882,7 +3892,8 @@ void main() {
}); });
test('RemoveMembersResponse', () { test('RemoveMembersResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -3995,7 +4006,8 @@ void main() {
}); });
test('AddMembersResponse', () { test('AddMembersResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -4108,7 +4120,8 @@ void main() {
}); });
test('AcceptInviteResponse', () { test('AcceptInviteResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -4221,7 +4234,8 @@ void main() {
}); });
test('RejectInviteResponse', () { test('RejectInviteResponse', () {
const jsonExample = r'''{"message":{ const jsonExample = r'''
{"message":{
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666", "id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.", "text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
"html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n", "html": "\u003cp\u003eWhat we dont know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
@@ -21,7 +21,7 @@ class FakeRequestOptions extends Fake implements RequestOptions {}
class MockHttpClientAdapter extends Mock implements HttpClientAdapter {} class MockHttpClientAdapter extends Mock implements HttpClientAdapter {}
class Functions { class Functions {
Future<String> tokenProvider(String userId) => null; Future<String> tokenProvider(String userId) async => '';
} }
class MockFunctions extends Mock implements Functions {} class MockFunctions extends Mock implements Functions {}
@@ -155,7 +155,9 @@ void main() {
'sort': sortOptions, 'sort': sortOptions,
} }
..addAll(options) ..addAll(options)
..addAll(paginationParams.toJson())), ..addAll(paginationParams
.toJson()
.map((key, value) => MapEntry(key, value as Object)))),
}; };
when( when(
+2 -2
View File
@@ -17,8 +17,8 @@ void main() {
final String pubspecPath = '${Directory.current.path}/pubspec.yaml'; final String pubspecPath = '${Directory.current.path}/pubspec.yaml';
final String pubspec = File(pubspecPath).readAsStringSync(); final String pubspec = File(pubspecPath).readAsStringSync();
final RegExp regex = RegExp('version:\s*(.*)'); final RegExp regex = RegExp('version:\s*(.*)');
final RegExpMatch match = regex.firstMatch(pubspec); final RegExpMatch? match = regex.firstMatch(pubspec);
expect(match, isNotNull); expect(match, isNotNull);
expect(PACKAGE_VERSION, match.group(1).trim()); expect(PACKAGE_VERSION, match?.group(1)?.trim());
}); });
} }