diff --git a/packages/stream_chat/lib/src/api/channel.dart b/packages/stream_chat/lib/src/api/channel.dart index 90bd6025..6fad7868 100644 --- a/packages/stream_chat/lib/src/api/channel.dart +++ b/packages/stream_chat/lib/src/api/channel.dart @@ -75,7 +75,7 @@ class Channel { /// Channel configuration ChannelConfig? get config { _checkInitialized(); - return state?._channelState?.channel?.config; + return state?._channelState.channel?.config; } /// Channel configuration as a stream @@ -87,7 +87,7 @@ class Channel { /// Channel user creator User? get createdBy { _checkInitialized(); - return state?._channelState?.channel?.createdBy; + return state?._channelState.channel?.createdBy; } /// Channel user creator as a stream @@ -99,7 +99,7 @@ class Channel { /// Channel frozen status bool? get frozen { _checkInitialized(); - return state?._channelState?.channel?.frozen; + return state?._channelState.channel?.frozen; } /// Channel frozen status as a stream @@ -111,7 +111,7 @@ class Channel { /// Channel creation date DateTime? get createdAt { _checkInitialized(); - return state?._channelState?.channel?.createdAt; + return state?._channelState.channel?.createdAt; } /// Channel creation date as a stream @@ -124,7 +124,7 @@ class Channel { DateTime? get lastMessageAt { _checkInitialized(); - return state?._channelState?.channel?.lastMessageAt; + return state?._channelState.channel?.lastMessageAt; } /// Channel last message date as a stream @@ -138,7 +138,7 @@ class Channel { DateTime? get updatedAt { _checkInitialized(); - return state?._channelState?.channel?.updatedAt; + return state?._channelState.channel?.updatedAt; } /// Channel updated date as a stream @@ -152,7 +152,7 @@ class Channel { DateTime? get deletedAt { _checkInitialized(); - return state?._channelState?.channel?.deletedAt; + return state?._channelState.channel?.deletedAt; } /// Channel deletion date as a stream @@ -166,7 +166,7 @@ class Channel { int? get memberCount { _checkInitialized(); - return state?._channelState?.channel?.memberCount; + return state?._channelState.channel?.memberCount; } /// Channel member count as a stream @@ -177,20 +177,20 @@ class Channel { } /// Channel id - String? get id => state?._channelState?.channel?.id ?? _id; + String? get id => state?._channelState.channel?.id ?? _id; /// Channel cid - String? get cid => state?._channelState?.channel?.cid ?? _cid; + String? get cid => state?._channelState.channel?.cid ?? _cid; /// Channel team String? get team { _checkInitialized(); - return state?._channelState?.channel?.team; + return state?._channelState.channel?.team; } /// Channel extra data Map? get extraData => - state?._channelState?.channel?.extraData ?? _extraData; + state?._channelState.channel?.extraData ?? _extraData; /// Channel extra data as a stream Stream?>? get extraDataStream { @@ -341,14 +341,15 @@ class Channel { /// Send a [message] to this channel. /// Waits for a [_messageAttachmentsUploadCompleter] to complete /// before actually sending the message. - Future sendMessage(Message message) async { + Future sendMessage(Message message) async { + _checkInitialized(); // Cancelling previous completer in case it's called again in the process // Eg. Updating the message while the previous call is in progress. _messageAttachmentsUploadCompleter .remove(message.id) ?.completeError('Message Cancelled'); - final quotedMessage = state?.messages.firstWhereOrNull( + final quotedMessage = state!.messages.firstWhereOrNull( (m) => m.id == message.quotedMessageId, ); // ignore: parameter_assignments @@ -365,7 +366,7 @@ class Channel { ).toList(), ); - state?.addMessage(message); + state!.addMessage(message); try { if (message.attachments.any((it) => !it.uploadState.isSuccess) == true) { @@ -384,11 +385,11 @@ class Channel { } final response = await _client.sendMessage(message, id!, type!); - state?.addMessage(response.message); + state!.addMessage(response.message); return response; } catch (error) { if (error is DioError && error.type != DioErrorType.response) { - state?.retryQueue?.add([message]); + state!.retryQueue?.add([message]); } rethrow; } @@ -397,7 +398,7 @@ class Channel { /// Updates the [message] in this channel. /// Waits for a [_messageAttachmentsUploadCompleter] to complete /// before actually updating the message. - Future updateMessage(Message message) async { + Future updateMessage(Message message) async { // Cancelling previous completer in case it's called again in the process // Eg. Updating the message while the previous call is in progress. _messageAttachmentsUploadCompleter @@ -452,7 +453,7 @@ class Channel { } /// Deletes the [message] from the channel. - Future deleteMessage(Message message) async { + Future deleteMessage(Message message) async { // Directly deleting the local messages which are not yet sent to server if (message.status == MessageSendingStatus.sending || message.status == MessageSendingStatus.failed) { @@ -493,7 +494,7 @@ class Channel { } /// Pins provided message - Future pinMessage( + Future pinMessage( Message message, Object? timeoutOrExpirationDate, ) { @@ -523,11 +524,11 @@ class Channel { } /// Unpins provided message - Future unpinMessage(Message message) => + Future unpinMessage(Message message) => updateMessage(message.copyWith(pinned: false)); /// Send a file to this channel - Future sendFile( + Future sendFile( AttachmentFile file, { ProgressCallback? onSendProgress, CancelToken? cancelToken, @@ -543,7 +544,7 @@ class Channel { } /// Send an image to this channel - Future sendImage( + Future sendImage( AttachmentFile file, { ProgressCallback? onSendProgress, CancelToken? cancelToken, @@ -559,7 +560,7 @@ class Channel { } /// A message search. - Future search({ + Future search({ String? query, Map? messageFilters, List? sort, @@ -578,7 +579,7 @@ class Channel { ); /// Delete a file from this channel - Future deleteFile( + Future deleteFile( String url, { CancelToken? cancelToken, }) { @@ -592,7 +593,7 @@ class Channel { } /// Delete an image from this channel - Future deleteImage( + Future deleteImage( String url, { CancelToken? cancelToken, }) { @@ -616,12 +617,13 @@ class Channel { /// Send a reaction to this channel /// Set [enforceUnique] to true to remove the existing user reaction - Future sendReaction( + Future sendReaction( Message message, String type, { Map extraData = const {}, bool enforceUnique = false, }) async { + _checkInitialized(); final messageId = message.id; final now = DateTime.now(); final user = _client.state.user; @@ -686,7 +688,7 @@ class Channel { } /// Delete a reaction from this channel - Future deleteReaction( + Future deleteReaction( Message message, Reaction reaction) async { final type = reaction.type; final user = _client.state.user; @@ -730,7 +732,7 @@ class Channel { } /// Edit the channel custom data - Future update( + Future update( Map channelData, [ Message? updateMessage, ]) async { @@ -743,40 +745,40 @@ class Channel { } /// Edit the channel custom data - Future updatePartial( + Future updatePartial( Map channelData) async { final response = await _client.patch(_channelURL, data: channelData); return _client.decode(response.data, PartialUpdateChannelResponse.fromJson); } /// Delete this channel. Messages are permanently removed. - Future delete() async { + Future delete() async { final response = await _client.delete(_channelURL); return _client.decode(response.data, EmptyResponse.fromJson); } /// Removes all messages from the channel - Future truncate() async { + Future truncate() async { final response = await _client.post('$_channelURL/truncate'); return _client.decode(response.data, EmptyResponse.fromJson); } /// Accept invitation to the channel - Future acceptInvite([Message? message]) async { + Future acceptInvite([Message? message]) async { final res = await _client.post(_channelURL, data: {'accept_invite': true, 'message': message?.toJson()}); return _client.decode(res.data, AcceptInviteResponse.fromJson); } /// Reject invitation to the channel - Future rejectInvite([Message? message]) async { + Future rejectInvite([Message? message]) async { final res = await _client.post(_channelURL, data: {'reject_invite': true, 'message': message?.toJson()}); return _client.decode(res.data, RejectInviteResponse.fromJson); } /// Add members to the channel - Future addMembers( + Future addMembers( List memberIds, [ Message? message, ]) async { @@ -788,7 +790,7 @@ class Channel { } /// Invite members to the channel - Future inviteMembers( + Future inviteMembers( List memberIds, [ Message? message, ]) async { @@ -800,7 +802,7 @@ class Channel { } /// Remove members from the channel - Future removeMembers( + Future removeMembers( List memberIds, [ Message? message, ]) async { @@ -836,7 +838,7 @@ class Channel { Message? oldMessage; if (oldIndex != -1) { oldMessage = state!.messages[oldIndex]; - state!.updateChannelState(state!._channelState!.copyWith( + state!.updateChannelState(state!._channelState.copyWith( messages: state?.messages?..remove(oldMessage), )); } else { @@ -863,7 +865,7 @@ class Channel { } /// Mark all channel messages as read - Future markRead() async { + Future markRead() async { _checkInitialized(); client.state.totalUnreadCount = max( 0, (client.state.totalUnreadCount ?? 0) - (state!.unreadCount ?? 0)); @@ -908,7 +910,7 @@ class Channel { } /// Stop watching the channel - Future stopWatching() async { + Future stopWatching() async { final response = await _client.post( '$_channelURL/stop-watching', data: {}, @@ -949,7 +951,7 @@ class Channel { } /// List the reactions for a message in the channel - Future getReactions( + Future getReactions( String messageID, PaginationParams options, ) async { @@ -982,7 +984,7 @@ class Channel { } /// Retrieves a list of messages by ID - Future translateMessage( + Future translateMessage( String messageId, String language, ) async { @@ -999,16 +1001,16 @@ class Channel { } /// Creates a new channel - Future? create() async => query(options: { + Future create() async => query(options: { 'watch': false, 'state': false, 'presence': false, - })!; + }); /// Query the API, get messages, members or other channel fields /// Set [preferOffline] to true to avoid the api call if the data is already /// in the offline storage - Future? query({ + Future query({ Map options = const {}, PaginationParams? messagesPagination, PaginationParams? membersPagination, @@ -1079,7 +1081,7 @@ class Channel { } /// Query channel members - Future queryMembers({ + Future queryMembers({ Map? filter, List? sort, PaginationParams? pagination, @@ -1108,7 +1110,7 @@ class Channel { } /// Mutes the channel - Future mute({Duration? expiration}) async { + Future mute({Duration? expiration}) async { final response = await _client.post('/moderation/mute/channel', data: { 'channel_cid': cid, if (expiration != null) 'expiration': expiration.inMilliseconds, @@ -1117,7 +1119,7 @@ class Channel { } /// Unmutes the channel - Future unmute() async { + Future unmute() async { final response = await _client.post('/moderation/unmute/channel', data: { 'channel_cid': cid, }); @@ -1125,7 +1127,7 @@ class Channel { } /// Bans a user from the channel - Future banUser( + Future banUser( String userID, Map options, ) async { @@ -1139,7 +1141,7 @@ class Channel { } /// Remove the ban for a user in the channel - Future unbanUser(String userID) async { + Future unbanUser(String userID) async { _checkInitialized(); return _client.unbanUser(userID, { 'type': type, @@ -1148,7 +1150,7 @@ class Channel { } /// Shadow bans a user from the channel - Future shadowBan( + Future shadowBan( String userID, Map options, ) async { @@ -1162,7 +1164,7 @@ class Channel { } /// Remove the shadow ban for a user in the channel - Future removeShadowBan(String userID) async { + Future removeShadowBan(String userID) async { _checkInitialized(); return _client.removeShadowBan(userID, { 'type': type, @@ -1173,7 +1175,7 @@ class Channel { /// Hides the channel from [StreamChatClient.queryChannels] for the user /// until a message is added If [clearHistory] is set to true - all messages /// will be removed for the user - Future hide({bool clearHistory = false}) async { + Future hide({bool clearHistory = false}) async { _checkInitialized(); final response = await _client .post('$_channelURL/hide', data: {'clear_history': clearHistory}); @@ -1190,7 +1192,7 @@ class Channel { } /// Removes the hidden status for the channel - Future show() async { + Future show() async { _checkInitialized(); final response = await _client.post('$_channelURL/show'); return _client.decode(response.data, EmptyResponse.fromJson); @@ -1257,9 +1259,10 @@ class Channel { void _checkInitialized() { assert( - !_initializedCompleter.isCompleted, - "Channel $cid hasn't been initialized yet. Make sure to call .watch()" - ' or to instantiate the client using [Channel.fromState]'); + _initializedCompleter.isCompleted, + "Channel $cid hasn't been initialized yet. Make sure to call .watch()" + ' or to instantiate the client using [Channel.fromState]', + ); } } @@ -1413,9 +1416,9 @@ class ChannelClientState { /// This flag should be managed by UI sdks. /// When false, any new message (received by WebSocket event /// - [EventType.messageNew]) will not be pushed on to message list. - bool? get isUpToDate => _isUpToDateController.value; + bool get isUpToDate => _isUpToDateController.value!; - set isUpToDate(bool? isUpToDate) => _isUpToDateController.add(isUpToDate); + set isUpToDate(bool isUpToDate) => _isUpToDateController.add(isUpToDate); /// [isUpToDate] flag count as a stream Stream get isUpToDateStream => _isUpToDateController.stream; @@ -1483,9 +1486,9 @@ class ChannelClientState { addMessage(message); if (message.pinned == true) { - _channelState = _channelState!.copyWith( + _channelState = _channelState.copyWith( pinnedMessages: [ - ..._channelState!.pinnedMessages, + ..._channelState.pinnedMessages, message, ], ); @@ -1522,7 +1525,7 @@ class ChannelClientState { /// Add a message to this channel void addMessage(Message message) { if (message.parentId == null || message.showInChannel == true) { - final newMessages = List.from(_channelState!.messages); + final newMessages = List.from(_channelState.messages); final oldIndex = newMessages.indexWhere((m) => m.id == message.id); if (oldIndex != -1) { Message? m; @@ -1537,9 +1540,9 @@ class ChannelClientState { newMessages.add(message); } - _channelState = _channelState!.copyWith( + _channelState = _channelState.copyWith( messages: newMessages, - channel: _channelState!.channel!.copyWith( + channel: _channelState.channel?.copyWith( lastMessageAt: message.createdAt, ), ); @@ -1551,7 +1554,7 @@ class ChannelClientState { } void _listenReadEvents() { - if (_channel.config?.readEvents == false) { + if (_channelState.channel?.config.readEvents == false) { return; } @@ -1563,7 +1566,7 @@ class ChannelClientState { ) .listen( (event) { - final readList = List.from(_channelState?.read ?? []); + final readList = List.from(_channelState.read); final userReadIndex = read?.indexWhere((r) => r.user.id == event.user!.id); @@ -1577,7 +1580,7 @@ class ChannelClientState { lastRead: event.createdAt!, unreadMessages: event.totalUnreadCount!, )); - _channelState = _channelState!.copyWith(read: readList); + _channelState = _channelState.copyWith(read: readList); } }, ), @@ -1585,22 +1588,22 @@ class ChannelClientState { } /// Channel message list - List get messages => _channelState!.messages; + List get messages => _channelState.messages; /// Channel message list as a stream Stream?> get messagesStream => channelStateStream.map((cs) => cs!.messages); /// Channel pinned message list - List? get pinnedMessages => _channelState!.pinnedMessages.toList(); + List? get pinnedMessages => _channelState.pinnedMessages.toList(); /// Channel pinned message list as a stream Stream?> get pinnedMessagesStream => channelStateStream.map((cs) => cs!.pinnedMessages.toList()); /// Get channel last message - Message? get lastMessage => _channelState!.messages.isNotEmpty == true - ? _channelState!.messages.last + Message? get lastMessage => _channelState.messages.isNotEmpty == true + ? _channelState.messages.last : null; /// Get channel last message @@ -1608,7 +1611,7 @@ class ChannelClientState { .map((event) => event?.isNotEmpty == true ? event!.last : null); /// Channel members list - List get members => _channelState!.members + List get members => _channelState.members .map((e) => e.copyWith(user: _channel.client.state.users[e.user!.id])) .toList(); @@ -1622,14 +1625,14 @@ class ChannelClientState { ); /// Channel watcher count - int? get watcherCount => _channelState!.watcherCount; + int? get watcherCount => _channelState.watcherCount; /// Channel watcher count as a stream Stream get watcherCountStream => channelStateStream.map((cs) => cs!.watcherCount); /// Channel watchers list - List get watchers => _channelState!.watchers + List get watchers => _channelState.watchers .map((e) => _channel.client.state.users[e.id] ?? e) .toList(); @@ -1642,7 +1645,7 @@ class ChannelClientState { ); /// Channel read list - List? get read => _channelState!.read; + List? get read => _channelState.read; /// Channel read list as a stream Stream?> get readStream => @@ -1693,7 +1696,7 @@ class ChannelClientState { /// Delete all channel messages void truncate() { - _channelState = _channelState!.copyWith( + _channelState = _channelState.copyWith( messages: [], ); } @@ -1704,24 +1707,22 @@ class ChannelClientState { void updateChannelState(ChannelState updatedState) { final newMessages = [ ...updatedState.messages, - ..._channelState?.messages - .where((m) => - updatedState.messages - .any((newMessage) => newMessage.id == m.id) != - true) - .toList() ?? - [], + ..._channelState.messages + .where((m) => + updatedState.messages + .any((newMessage) => newMessage.id == m.id) != + true) + .toList(), ]..sort(_sortByCreatedAt as int Function(Message, Message)?); final newWatchers = [ ...updatedState.watchers, - ..._channelState?.watchers - .where((w) => - updatedState.watchers - .any((newWatcher) => newWatcher.id == w.id) != - true) - .toList() ?? - [], + ..._channelState.watchers + .where((w) => + updatedState.watchers + .any((newWatcher) => newWatcher.id == w.id) != + true) + .toList(), ]; final newMembers = [ @@ -1730,20 +1731,19 @@ class ChannelClientState { final newReads = [ ...updatedState.read, - ..._channelState?.read - .where((r) => - updatedState.read - .any((newRead) => newRead.user.id == r.user.id) != - true) - .toList() ?? - [], + ..._channelState.read + .where((r) => + updatedState.read + .any((newRead) => newRead.user.id == r.user.id) != + true) + .toList(), ]; _checkExpiredAttachmentMessages(updatedState); - _channelState = _channelState!.copyWith( + _channelState = _channelState.copyWith( messages: newMessages, - channel: _channelState!.channel?.merge(updatedState.channel), + channel: _channelState.channel?.merge(updatedState.channel), watchers: newWatchers, watcherCount: updatedState.watcherCount, members: newMembers, @@ -1765,7 +1765,7 @@ class ChannelClientState { } /// The channel state related to this client - ChannelState? get _channelState => _channelStateController.value; + ChannelState get _channelState => _channelStateController.value!; /// The channel state related to this client as a stream Stream get channelStateStream => @@ -1773,11 +1773,11 @@ class ChannelClientState { /// The channel state related to this client ChannelState? get channelState => _channelStateController.value; - late BehaviorSubject _channelStateController; + late BehaviorSubject _channelStateController; final Debounce _debouncedUpdatePersistenceChannelState; - set _channelState(ChannelState? v) { + set _channelState(ChannelState v) { _channelStateController.add(v); _debouncedUpdatePersistenceChannelState.call([v]); } @@ -1812,7 +1812,7 @@ class ChannelClientState { final Map _typings = {}; void _listenTypingEvents() { - if (_channel.config?.typingEvents == false) { + if (_channelState.channel?.config.typingEvents == false) { return; } @@ -1867,7 +1867,7 @@ class ChannelClientState { late Timer _cleaningTimer; void _startCleaning() { - if (_channel.config?.typingEvents == false) { + if (_channelState.channel?.config.typingEvents == false) { return; } @@ -1899,7 +1899,7 @@ class ChannelClientState { )) .toList(); - updateChannelState(_channelState!.copyWith( + updateChannelState(_channelState.copyWith( pinnedMessages: pinnedMessages!.where(_pinIsValid()).toList(), messages: expiredMessages, )); diff --git a/packages/stream_chat/lib/src/models/reaction.dart b/packages/stream_chat/lib/src/models/reaction.dart index eefeaebe..82913218 100644 --- a/packages/stream_chat/lib/src/models/reaction.dart +++ b/packages/stream_chat/lib/src/models/reaction.dart @@ -12,11 +12,11 @@ class Reaction { this.messageId, DateTime? createdAt, required this.type, - required this.user, + this.user, String? userId, this.score = 0, this.extraData, - }) : userId = userId ?? user.id, + }) : userId = userId ?? user?.id, createdAt = createdAt ?? DateTime.now(); /// Create a new instance from a json @@ -38,7 +38,7 @@ class Reaction { /// The user that sent the reaction @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) - final User user; + final User? user; /// The score of the reaction (ie. number of reactions sent) @JsonKey(defaultValue: 0) diff --git a/packages/stream_chat/lib/src/models/reaction.g.dart b/packages/stream_chat/lib/src/models/reaction.g.dart index 203be6eb..963b4d21 100644 --- a/packages/stream_chat/lib/src/models/reaction.g.dart +++ b/packages/stream_chat/lib/src/models/reaction.g.dart @@ -13,7 +13,9 @@ Reaction _$ReactionFromJson(Map json) { ? null : DateTime.parse(json['created_at'] as String), type: json['type'] as String, - user: User.fromJson(json['user'] as Map), + user: json['user'] == null + ? null + : User.fromJson(json['user'] as Map), userId: json['user_id'] as String?, score: json['score'] as int? ?? 0, extraData: json['extra_data'] as Map?, diff --git a/packages/stream_chat/test/src/api/channel_test.dart b/packages/stream_chat/test/src/api/channel_test.dart index e0a29cc8..b41214d2 100644 --- a/packages/stream_chat/test/src/api/channel_test.dart +++ b/packages/stream_chat/test/src/api/channel_test.dart @@ -38,6 +38,17 @@ void main() { final channelClient = client.channel('messaging', id: 'testid'); final message = Message(text: 'hey', id: 'test'); + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when( () => mockDio.post( '/channels/messaging/testid/message', @@ -45,7 +56,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': message}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -227,6 +238,17 @@ void main() { ); final channelClient = client.channel(channelType, id: channelId); + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when(() => mockUploader.sendFile(file, channelId, channelType)) .thenAnswer((_) async => SendFileResponse()); @@ -255,6 +277,17 @@ void main() { ); final channelClient = client.channel(channelType, id: channelId); + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when(() => mockUploader.sendImage(image, channelId, channelType)) .thenAnswer((_) async => SendImageResponse()); @@ -278,6 +311,17 @@ void main() { final channelClient = client.channel('messaging', id: 'testid'); const url = 'url'; + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when( () => mockDio.delete( '/channels/messaging/testid/file', @@ -311,6 +355,17 @@ void main() { final channelClient = client.channel('messaging', id: 'testid'); const url = 'url'; + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when( () => mockDio.delete( '/channels/messaging/testid/image', @@ -357,6 +412,17 @@ void main() { final channelClient = client.channel('messaging', id: 'testid'); final message = Message(text: 'Hello', id: 'test'); + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when( () => mockDio.post( '/messages/${message.id}', @@ -364,7 +430,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': message}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -391,6 +457,17 @@ void main() { final channelClient = client.channel('messaging', id: 'testid'); final message = Message(text: 'Hello', id: 'test'); + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState()), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + when( () => mockDio.post( '/messages/${message.id}', @@ -398,7 +475,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': message}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -567,14 +644,30 @@ void main() { tokenProvider: (_) async => '', ); - client.state.user = OwnUser(id: 'test-id'); + final user = OwnUser(id: 'test-id'); - final channelClient = client.channel('messaging', id: 'testid'); + client.state.user = user; + + final message = Message(id: 'messageid'); const reactionType = 'test'; + final reaction = Reaction(type: reactionType); + final channelClient = client.channel('messaging', id: 'testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer( + (_) async => Response( + data: '{}', + statusCode: 200, + requestOptions: FakeRequestOptions(), + ), + ); + await channelClient.watch(); when( () => mockDio.post( - '/messages/messageid/reaction', + '/messages/${message.id}/reaction', data: { 'reaction': { 'type': reactionType, @@ -584,16 +677,17 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'message': message, + 'reaction': reaction, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), ); await channelClient.sendReaction( - Message( - id: 'messageid', - ), + message, reactionType, ); @@ -697,26 +791,44 @@ void main() { tokenProvider: (_) async => '', ); final channelClient = client.channel('messaging', id: 'testid'); - final members = ['vishal']; + final channelModel = ChannelModel(cid: 'messaging:testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState(channel: channelModel)), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + + final members = [Member(userId: 'vishal')]; + final memberIds = members.map((e) => e.userId!).toList(); final message = Message(text: 'test'); when( () => mockDio.post( '/channels/messaging/testid', - data: {'add_members': members, 'message': message.toJson()}, + data: {'add_members': memberIds, 'message': message.toJson()}, ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'members': members, + 'message': message, + 'channel': channelModel, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), ); - await channelClient.addMembers(members, message); + await channelClient.addMembers(memberIds, message); verify(() => mockDio.post('/channels/messaging/testid', - data: {'add_members': members, 'message': message.toJson()})) + data: {'add_members': memberIds, 'message': message.toJson()})) .called(1); }); @@ -732,6 +844,19 @@ void main() { tokenProvider: (_) async => '', ); final channelClient = client.channel('messaging', id: 'testid'); + final channelModel = ChannelModel(cid: 'messaging:testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState(channel: channelModel)), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + final message = Message(text: 'test'); when( @@ -741,7 +866,10 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'message': message, + 'channel': channelModel, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -2080,6 +2208,19 @@ void main() { tokenProvider: (_) async => '', ); final channelClient = client.channel('messaging', id: 'testid'); + final channelModel = ChannelModel(cid: 'messaging:testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState(channel: channelModel)), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + final message = Message(text: 'test'); when( @@ -2092,7 +2233,10 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'channel': channelModel, + 'message': message, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -2179,6 +2323,19 @@ void main() { tokenProvider: (_) async => '', ); final channelClient = client.channel('messaging', id: 'testid'); + final channelModel = ChannelModel(cid: 'messaging:testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState(channel: channelModel)), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + final message = Message(text: 'test'); when( @@ -2188,7 +2345,10 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'message': message, + 'channel': channelModel, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -2213,26 +2373,45 @@ void main() { tokenProvider: (_) async => '', ); final channelClient = client.channel('messaging', id: 'testid'); - final members = ['vishal']; + final channelModel = ChannelModel(cid: 'messaging:testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState(channel: channelModel)), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + + final members = [Member(userId: 'vishal')]; + final memberIds = members.map((e) => e.userId!).toList(); final message = Message(text: 'test'); when( () => mockDio.post( '/channels/messaging/testid', - data: {'invites': members, 'message': message.toJson()}, + data: {'invites': memberIds, 'message': message.toJson()}, ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'members': members, + 'message': message, + 'channel': channelModel, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), ); - await channelClient.inviteMembers(members, message); + await channelClient.inviteMembers(memberIds, message); verify(() => mockDio.post('/channels/messaging/testid', - data: {'invites': members, 'message': message.toJson()})).called(1); + data: {'invites': memberIds, 'message': message.toJson()})) + .called(1); }); test('removeMembers', () async { @@ -2247,27 +2426,46 @@ void main() { tokenProvider: (_) async => '', ); final channelClient = client.channel('messaging', id: 'testid'); - final members = ['vishal']; + final channelModel = ChannelModel(cid: 'messaging:testid'); + + when(() => mockDio.post( + any(), + data: any(named: 'data'), + )).thenAnswer((_) async => Response( + data: jsonEncode(ChannelState(channel: channelModel)), + statusCode: 200, + requestOptions: FakeRequestOptions(), + )); + + await channelClient.watch(); + + final members = [Member(userId: 'vishal')]; + final memberIds = members.map((e) => e.userId!).toList(); final message = Message(text: 'test'); when( () => mockDio.post( '/channels/messaging/testid', - data: {'remove_members': members, 'message': message.toJson()}, + data: {'remove_members': memberIds, 'message': message.toJson()}, ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({ + 'members': members, + 'message': message, + 'channel': channelModel, + }), statusCode: 200, requestOptions: FakeRequestOptions(), ), ); - await channelClient.removeMembers(members, message); + await channelClient.removeMembers(memberIds, message); - verify(() => mockDio.post('/channels/messaging/testid', - data: {'remove_members': members, 'message': message.toJson()})) - .called(1); + verify(() => mockDio.post('/channels/messaging/testid', data: { + 'remove_members': memberIds, + 'message': message.toJson() + })).called(1); }); test('hide', () async {