diff --git a/packages/stream_chat/lib/src/api/channel.dart b/packages/stream_chat/lib/src/api/channel.dart index f868e6e0..90bd6025 100644 --- a/packages/stream_chat/lib/src/api/channel.dart +++ b/packages/stream_chat/lib/src/api/channel.dart @@ -59,13 +59,12 @@ class Channel { /// Returns true if the channel is muted bool get isMuted => _client.state.user?.channelMutes - .any((element) => element.channel!.cid == cid) == + .any((element) => element.channel.cid == cid) == true; /// Returns true if the channel is muted as a stream Stream? get isMutedStream => _client.state.userStream.map((event) => - event!.channelMutes.any((element) => element.channel!.cid == cid) == - true); + event!.channelMutes.any((element) => element.channel.cid == cid) == true); /// True if the channel is a group bool get isGroup => memberCount != 2; @@ -74,85 +73,130 @@ class Channel { bool get isDistinct => id?.startsWith('!members') == true; /// Channel configuration - ChannelConfig? get config => state?._channelState?.channel?.config; + ChannelConfig? get config { + _checkInitialized(); + return state?._channelState?.channel?.config; + } /// Channel configuration as a stream - Stream? get configStream => - state?.channelStateStream.map((cs) => cs!.channel?.config); + Stream? get configStream { + _checkInitialized(); + return state?.channelStateStream.map((cs) => cs!.channel?.config); + } /// Channel user creator - User? get createdBy => state?._channelState?.channel?.createdBy; + User? get createdBy { + _checkInitialized(); + return state?._channelState?.channel?.createdBy; + } /// Channel user creator as a stream - Stream? get createdByStream => - state?.channelStateStream.map((cs) => cs!.channel?.createdBy); + Stream? get createdByStream { + _checkInitialized(); + return state?.channelStateStream.map((cs) => cs!.channel?.createdBy); + } /// Channel frozen status - bool? get frozen => state?._channelState?.channel?.frozen; + bool? get frozen { + _checkInitialized(); + return state?._channelState?.channel?.frozen; + } /// Channel frozen status as a stream - Stream? get frozenStream => - state?.channelStateStream.map((cs) => cs!.channel?.frozen); + Stream? get frozenStream { + _checkInitialized(); + return state?.channelStateStream.map((cs) => cs!.channel?.frozen); + } /// Channel creation date - DateTime? get createdAt => state?._channelState?.channel?.createdAt; + DateTime? get createdAt { + _checkInitialized(); + return state?._channelState?.channel?.createdAt; + } /// Channel creation date as a stream - Stream? get createdAtStream => - state?.channelStateStream.map((cs) => cs!.channel?.createdAt); + Stream? get createdAtStream { + _checkInitialized(); + return state?.channelStateStream.map((cs) => cs!.channel?.createdAt); + } /// Channel last message date - DateTime? get lastMessageAt => state?._channelState?.channel?.lastMessageAt; + DateTime? get lastMessageAt { + _checkInitialized(); + + return state?._channelState?.channel?.lastMessageAt; + } /// Channel last message date as a stream - Stream? get lastMessageAtStream => - state?.channelStateStream.map((cs) => cs!.channel?.lastMessageAt); + Stream? get lastMessageAtStream { + _checkInitialized(); + + return state?.channelStateStream.map((cs) => cs!.channel?.lastMessageAt); + } /// Channel updated date - DateTime? get updatedAt => state?._channelState?.channel?.updatedAt; + DateTime? get updatedAt { + _checkInitialized(); + + return state?._channelState?.channel?.updatedAt; + } /// Channel updated date as a stream - Stream? get updatedAtStream => - state?.channelStateStream.map((cs) => cs!.channel?.updatedAt); + Stream? get updatedAtStream { + _checkInitialized(); + + return state?.channelStateStream.map((cs) => cs!.channel?.updatedAt); + } /// Channel deletion date - DateTime? get deletedAt => state?._channelState?.channel?.deletedAt; + DateTime? get deletedAt { + _checkInitialized(); + + return state?._channelState?.channel?.deletedAt; + } /// Channel deletion date as a stream - Stream? get deletedAtStream => - state?.channelStateStream.map((cs) => cs!.channel?.deletedAt); + Stream? get deletedAtStream { + _checkInitialized(); + + return state?.channelStateStream.map((cs) => cs!.channel?.deletedAt); + } /// Channel member count - int? get memberCount => state?._channelState?.channel?.memberCount; + int? get memberCount { + _checkInitialized(); + + return state?._channelState?.channel?.memberCount; + } /// Channel member count as a stream - Stream? get memberCountStream => - state?.channelStateStream.map((cs) => cs!.channel?.memberCount); + Stream? get memberCountStream { + _checkInitialized(); + + return state?.channelStateStream.map((cs) => cs!.channel?.memberCount); + } /// Channel id String? get id => state?._channelState?.channel?.id ?? _id; - /// Channel id as a stream - Stream? get idStream => - state?.channelStateStream.map((cs) => cs!.channel?.id ?? _id); - /// Channel cid String? get cid => state?._channelState?.channel?.cid ?? _cid; /// Channel team - String? get team => state?._channelState?.channel?.team; - - /// Channel cid as a stream - Stream? get cidStream => - state?.channelStateStream.map((cs) => cs!.channel?.cid ?? _cid); + String? get team { + _checkInitialized(); + return state?._channelState?.channel?.team; + } /// Channel extra data Map? get extraData => state?._channelState?.channel?.extraData ?? _extraData; /// Channel extra data as a stream - Stream?>? get extraDataStream => - state?.channelStateStream.map((cs) => cs!.channel?.extraData); + Stream?>? get extraDataStream { + _checkInitialized(); + return state?.channelStateStream.map((cs) => cs!.channel?.extraData); + } /// The main Stream chat client StreamChatClient get client => _client; @@ -205,14 +249,14 @@ class Channel { throw Exception('Error, Message not found'); } - final attachments = message.attachments!.where((it) { + final attachments = message.attachments.where((it) { if (it.uploadState.isSuccess) return false; return attachmentIds.contains(it.id); }); if (attachments.isEmpty) { client.logger.info('No attachments available to upload'); - if (message.attachments!.every((it) => it.uploadState.isSuccess)) { + if (message.attachments.every((it) => it.uploadState.isSuccess)) { _messageAttachmentsUploadCompleter.remove(messageId)?.complete(message); } return Future.value(); @@ -222,9 +266,9 @@ class Channel { void updateAttachment(Attachment attachment) { final index = - message.attachments!.indexWhere((it) => it.id == attachment.id); + message.attachments.indexWhere((it) => it.id == attachment.id); if (index != -1) { - message.attachments![index] = attachment; + message.attachments[index] = attachment; state?.addMessage(message); } } @@ -252,13 +296,13 @@ class Channel { it.file!, onSendProgress: onSendProgress, cancelToken: cancelToken, - ).then((it) => it!.file!); + ).then((it) => it!.file); } else { future = sendFile( it.file!, onSendProgress: onSendProgress, cancelToken: cancelToken, - ).then((it) => it!.file!); + ).then((it) => it!.file); } _cancelableAttachmentUploadRequest[it.id] = cancelToken; return future.then((url) { @@ -288,7 +332,7 @@ class Channel { _cancelableAttachmentUploadRequest.remove(it.id); }); })).whenComplete(() { - if (message.attachments!.every((it) => it.uploadState.isSuccess)) { + if (message.attachments.every((it) => it.uploadState.isSuccess)) { _messageAttachmentsUploadCompleter.remove(messageId)?.complete(message); } }); @@ -313,7 +357,7 @@ class Channel { user: _client.state.user, quotedMessage: quotedMessage, status: MessageSendingStatus.sending, - attachments: message.attachments?.map( + attachments: message.attachments.map( (it) { if (it.uploadState.isSuccess) return it; return it.copyWith(uploadState: const UploadState.preparing()); @@ -324,7 +368,7 @@ class Channel { state?.addMessage(message); try { - if (message.attachments?.any((it) => !it.uploadState.isSuccess) == true) { + if (message.attachments.any((it) => !it.uploadState.isSuccess) == true) { final attachmentsUploadCompleter = Completer(); _messageAttachmentsUploadCompleter[message.id] = attachmentsUploadCompleter; @@ -332,15 +376,15 @@ class Channel { // ignore: unawaited_futures _uploadAttachments( message.id, - message.attachments!.map((it) => it.id), + message.attachments.map((it) => it.id), ); // ignore: parameter_assignments message = await attachmentsUploadCompleter.future; } - final response = await _client.sendMessage(message, id, type); - state?.addMessage(response.message!); + final response = await _client.sendMessage(message, id!, type!); + state?.addMessage(response.message); return response; } catch (error) { if (error is DioError && error.type != DioErrorType.response) { @@ -364,7 +408,7 @@ class Channel { message = message.copyWith( status: MessageSendingStatus.updating, updatedAt: message.updatedAt, - attachments: message.attachments?.map( + attachments: message.attachments.map( (it) { if (it.uploadState.isSuccess) return it; return it.copyWith(uploadState: const UploadState.preparing()); @@ -375,7 +419,7 @@ class Channel { state?.addMessage(message); try { - if (message.attachments?.any((it) => !it.uploadState.isSuccess) == true) { + if (message.attachments.any((it) => !it.uploadState.isSuccess) == true) { final attachmentsUploadCompleter = Completer(); _messageAttachmentsUploadCompleter[message.id] = attachmentsUploadCompleter; @@ -383,7 +427,7 @@ class Channel { // ignore: unawaited_futures _uploadAttachments( message.id, - message.attachments!.map((it) => it.id), + message.attachments.map((it) => it.id), ); // ignore: parameter_assignments @@ -392,13 +436,11 @@ class Channel { final response = await _client.updateMessage(message); - final m = response.message?.copyWith( + final m = response.message.copyWith( ownReactions: message.ownReactions, ); - if (m != null) { - state?.addMessage(m); - } + state?.addMessage(m); return response; } catch (error) { @@ -489,28 +531,32 @@ class Channel { AttachmentFile file, { ProgressCallback? onSendProgress, CancelToken? cancelToken, - }) => - _client.sendFile( - file, - id, - type, - onSendProgress: onSendProgress, - cancelToken: cancelToken, - ); + }) { + _checkInitialized(); + return _client.sendFile( + file, + id!, + type!, + onSendProgress: onSendProgress, + cancelToken: cancelToken, + ); + } /// Send an image to this channel Future sendImage( AttachmentFile file, { ProgressCallback? onSendProgress, CancelToken? cancelToken, - }) => - _client.sendImage( - file, - id, - type, - onSendProgress: onSendProgress, - cancelToken: cancelToken, - ); + }) { + _checkInitialized(); + return _client.sendImage( + file, + id!, + type!, + onSendProgress: onSendProgress, + cancelToken: cancelToken, + ); + } /// A message search. Future search({ @@ -535,15 +581,29 @@ class Channel { Future deleteFile( String url, { CancelToken? cancelToken, - }) => - _client.deleteFile(url, id, type, cancelToken: cancelToken); + }) { + _checkInitialized(); + return _client.deleteFile( + url, + id!, + type!, + cancelToken: cancelToken, + ); + } /// Delete an image from this channel Future deleteImage( String url, { CancelToken? cancelToken, - }) => - _client.deleteImage(url, id, type, cancelToken: cancelToken); + }) { + _checkInitialized(); + return _client.deleteImage( + url, + id!, + type!, + cancelToken: cancelToken, + ); + } /// Send an event on this channel Future sendEvent(Event event) { @@ -916,9 +976,7 @@ class Channel { final messages = res.messages; - if (messages != null) { - state?.updateChannelState(ChannelState(messages: messages)); - } + state?.updateChannelState(ChannelState(messages: messages)); return res; } @@ -1198,11 +1256,10 @@ class Channel { } void _checkInitialized() { - if (!_initializedCompleter.isCompleted) { - throw Exception( - "Channel $cid hasn't been initialized yet. Make sure to call .watch()" - ' or to instantiate the client using [Channel.fromState]'); - } + assert( + !_initializedCompleter.isCompleted, + "Channel $cid hasn't been initialized yet. Make sure to call .watch()" + ' or to instantiate the client using [Channel.fromState]'); } } @@ -1285,8 +1342,8 @@ class ChannelClientState { final expiredAttachmentMessagesId = channelState.messages .where((m) => !_updatedMessagesIds.contains(m.id) && - m.attachments?.isNotEmpty == true && - m.attachments?.any((e) { + m.attachments.isNotEmpty == true && + m.attachments.any((e) { final url = e.imageUrl ?? e.assetUrl; if (url == null || !url.contains('')) { return false; @@ -1602,12 +1659,12 @@ class ChannelClientState { bool _countMessageAsUnread(Message message) { final userId = _channel.client.state.user?.id; final userIsMuted = _channel.client.state.user?.mutes.firstWhereOrNull( - (m) => m.user?.id == message.user!.id, + (m) => m.user.id == message.user?.id, ) != null; return message.silent != true && message.shadowed != true && - message.user!.id != userId && + message.user?.id != userId && !userIsMuted; } diff --git a/packages/stream_chat/lib/src/api/responses.dart b/packages/stream_chat/lib/src/api/responses.dart index a26fc626..a64cd64e 100644 --- a/packages/stream_chat/lib/src/api/responses.dart +++ b/packages/stream_chat/lib/src/api/responses.dart @@ -20,186 +20,194 @@ class _BaseResponse { @JsonSerializable(createToJson: false) class SyncResponse extends _BaseResponse { /// The list of events - List? events; + @JsonKey(defaultValue: []) + late List events; /// Create a new instance from a json - static SyncResponse fromJson(Map? json) => - _$SyncResponseFromJson(json!); + static SyncResponse fromJson(Map json) => + _$SyncResponseFromJson(json); } /// Model response for [StreamChatClient.queryChannels] api call @JsonSerializable(createToJson: false) class QueryChannelsResponse extends _BaseResponse { /// List of channels state returned by the query - List? channels; + @JsonKey(defaultValue: []) + late List channels; /// Create a new instance from a json - static QueryChannelsResponse fromJson(Map? json) => - _$QueryChannelsResponseFromJson(json!); + static QueryChannelsResponse fromJson(Map json) => + _$QueryChannelsResponseFromJson(json); } /// Model response for [StreamChatClient.queryChannels] api call @JsonSerializable(createToJson: false) class TranslateMessageResponse extends _BaseResponse { - /// List of channels state returned by the query - TranslatedMessage? message; + /// Translated message + late TranslatedMessage message; /// Create a new instance from a json - static TranslateMessageResponse fromJson(Map? json) => - _$TranslateMessageResponseFromJson(json!); + static TranslateMessageResponse fromJson(Map json) => + _$TranslateMessageResponseFromJson(json); } /// Model response for [StreamChatClient.queryChannels] api call @JsonSerializable(createToJson: false) class QueryMembersResponse extends _BaseResponse { /// List of channels state returned by the query - List? members; + @JsonKey(defaultValue: []) + late List members; /// Create a new instance from a json - static QueryMembersResponse fromJson(Map? json) => - _$QueryMembersResponseFromJson(json!); + static QueryMembersResponse fromJson(Map json) => + _$QueryMembersResponseFromJson(json); } /// Model response for [StreamChatClient.queryUsers] api call @JsonSerializable(createToJson: false) class QueryUsersResponse extends _BaseResponse { /// List of users returned by the query - List? users; + @JsonKey(defaultValue: []) + late List users; /// Create a new instance from a json - static QueryUsersResponse fromJson(Map? json) => - _$QueryUsersResponseFromJson(json!); + static QueryUsersResponse fromJson(Map json) => + _$QueryUsersResponseFromJson(json); } /// Model response for [channel.getReactions] api call @JsonSerializable(createToJson: false) class QueryReactionsResponse extends _BaseResponse { /// List of reactions returned by the query - List? reactions; + @JsonKey(defaultValue: []) + late List reactions; /// Create a new instance from a json - static QueryReactionsResponse fromJson(Map? json) => - _$QueryReactionsResponseFromJson(json!); + static QueryReactionsResponse fromJson(Map json) => + _$QueryReactionsResponseFromJson(json); } /// Model response for [Channel.getReplies] api call @JsonSerializable(createToJson: false) class QueryRepliesResponse extends _BaseResponse { /// List of messages returned by the api call - List? messages; + @JsonKey(defaultValue: []) + late List messages; /// Create a new instance from a json - static QueryRepliesResponse fromJson(Map? json) => - _$QueryRepliesResponseFromJson(json!); + static QueryRepliesResponse fromJson(Map json) => + _$QueryRepliesResponseFromJson(json); } /// Model response for [StreamChatClient.getDevices] api call @JsonSerializable(createToJson: false) class ListDevicesResponse extends _BaseResponse { /// List of user devices - List? devices; + @JsonKey(defaultValue: []) + late List devices; /// Create a new instance from a json - static ListDevicesResponse fromJson(Map? json) => - _$ListDevicesResponseFromJson(json!); + static ListDevicesResponse fromJson(Map json) => + _$ListDevicesResponseFromJson(json); } /// Model response for [Channel.sendFile] api call @JsonSerializable(createToJson: false) class SendFileResponse extends _BaseResponse { /// The url of the uploaded file - String? file; + late String file; /// Create a new instance from a json - static SendFileResponse fromJson(Map? json) => - _$SendFileResponseFromJson(json!); + static SendFileResponse fromJson(Map json) => + _$SendFileResponseFromJson(json); } /// Model response for [Channel.sendImage] api call @JsonSerializable(createToJson: false) class SendImageResponse extends _BaseResponse { /// The url of the uploaded file - String? file; + late String file; /// Create a new instance from a json - static SendImageResponse fromJson(Map? json) => - _$SendImageResponseFromJson(json!); + static SendImageResponse fromJson(Map json) => + _$SendImageResponseFromJson(json); } /// Model response for [Channel.sendReaction] api call @JsonSerializable(createToJson: false) class SendReactionResponse extends _BaseResponse { /// Message returned by the api call - Message? message; + late Message message; /// The reaction created by the api call - Reaction? reaction; + late Reaction reaction; /// Create a new instance from a json - static SendReactionResponse fromJson(Map? json) => - _$SendReactionResponseFromJson(json!); + static SendReactionResponse fromJson(Map json) => + _$SendReactionResponseFromJson(json); } /// Model response for [StreamChatClient.connectGuestUser] api call @JsonSerializable(createToJson: false) class ConnectGuestUserResponse extends _BaseResponse { /// Guest user access token - String? accessToken; + late String accessToken; /// Guest user - User? user; + late User user; /// Create a new instance from a json - static ConnectGuestUserResponse fromJson(Map? json) => - _$ConnectGuestUserResponseFromJson(json!); + static ConnectGuestUserResponse fromJson(Map json) => + _$ConnectGuestUserResponseFromJson(json); } /// Model response for [StreamChatClient.updateUser] api call @JsonSerializable(createToJson: false) class UpdateUsersResponse extends _BaseResponse { /// Updated users - Map? users; + @JsonKey(defaultValue: {}) + late Map users; /// Create a new instance from a json - static UpdateUsersResponse fromJson(Map? json) => - _$UpdateUsersResponseFromJson(json!); + static UpdateUsersResponse fromJson(Map json) => + _$UpdateUsersResponseFromJson(json); } /// Model response for [StreamChatClient.updateMessage] api call @JsonSerializable(createToJson: false) class UpdateMessageResponse extends _BaseResponse { /// Message returned by the api call - Message? message; + late Message message; /// Create a new instance from a json - static UpdateMessageResponse fromJson(Map? json) => - _$UpdateMessageResponseFromJson(json!); + static UpdateMessageResponse fromJson(Map json) => + _$UpdateMessageResponseFromJson(json); } /// Model response for [Channel.sendMessage] api call @JsonSerializable(createToJson: false) class SendMessageResponse extends _BaseResponse { /// Message returned by the api call - Message? message; + late Message message; /// Create a new instance from a json - static SendMessageResponse fromJson(Map? json) => - _$SendMessageResponseFromJson(json!); + static SendMessageResponse fromJson(Map json) => + _$SendMessageResponseFromJson(json); } /// Model response for [StreamChatClient.getMessage] api call @JsonSerializable(createToJson: false) class GetMessageResponse extends _BaseResponse { /// Message returned by the api call - Message? message; + late Message message; /// Channel of the message ChannelModel? channel; /// Create a new instance from a json - static GetMessageResponse fromJson(Map? json) { - final res = _$GetMessageResponseFromJson(json!); - final jsonChannel = res.message?.extraData?.remove('channel'); + static GetMessageResponse fromJson(Map json) { + final res = _$GetMessageResponseFromJson(json); + final jsonChannel = res.message.extraData.remove('channel'); if (jsonChannel != null) { res.channel = ChannelModel.fromJson(jsonChannel); } @@ -211,29 +219,31 @@ class GetMessageResponse extends _BaseResponse { @JsonSerializable(createToJson: false) class SearchMessagesResponse extends _BaseResponse { /// List of messages returned by the api call - List? results; + @JsonKey(defaultValue: []) + late List results; /// Create a new instance from a json - static SearchMessagesResponse fromJson(Map? json) => - _$SearchMessagesResponseFromJson(json!); + static SearchMessagesResponse fromJson(Map json) => + _$SearchMessagesResponseFromJson(json); } /// Model response for [Channel.getMessagesById] api call @JsonSerializable(createToJson: false) class GetMessagesByIdResponse extends _BaseResponse { /// Message returned by the api call - List? messages; + @JsonKey(defaultValue: []) + late List messages; /// Create a new instance from a json - static GetMessagesByIdResponse fromJson(Map? json) => - _$GetMessagesByIdResponseFromJson(json!); + static GetMessagesByIdResponse fromJson(Map json) => + _$GetMessagesByIdResponseFromJson(json); } /// Model response for [Channel.update] api call @JsonSerializable(createToJson: false) class UpdateChannelResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members List? members; @@ -242,56 +252,58 @@ class UpdateChannelResponse extends _BaseResponse { Message? message; /// Create a new instance from a json - static UpdateChannelResponse fromJson(Map? json) => - _$UpdateChannelResponseFromJson(json!); + static UpdateChannelResponse fromJson(Map json) => + _$UpdateChannelResponseFromJson(json); } /// Model response for [Channel.updatePartial] api call @JsonSerializable(createToJson: false) class PartialUpdateChannelResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members List? members; /// Create a new instance from a json - static PartialUpdateChannelResponse fromJson(Map? json) => - _$PartialUpdateChannelResponseFromJson(json!); + static PartialUpdateChannelResponse fromJson(Map json) => + _$PartialUpdateChannelResponseFromJson(json); } /// Model response for [Channel.inviteMembers] api call @JsonSerializable(createToJson: false) class InviteMembersResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members - List? members; + @JsonKey(defaultValue: []) + late List members; /// Message returned by the api call Message? message; /// Create a new instance from a json - static InviteMembersResponse fromJson(Map? json) => - _$InviteMembersResponseFromJson(json!); + static InviteMembersResponse fromJson(Map json) => + _$InviteMembersResponseFromJson(json); } /// Model response for [Channel.removeMembers] api call @JsonSerializable(createToJson: false) class RemoveMembersResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members - List? members; + @JsonKey(defaultValue: []) + late List members; /// Message returned by the api call Message? message; /// Create a new instance from a json - static RemoveMembersResponse fromJson(Map? json) => - _$RemoveMembersResponseFromJson(json!); + static RemoveMembersResponse fromJson(Map json) => + _$RemoveMembersResponseFromJson(json); } /// Model response for [Channel.sendAction] api call @@ -301,86 +313,93 @@ class SendActionResponse extends _BaseResponse { Message? message; /// Create a new instance from a json - static SendActionResponse fromJson(Map? json) => - _$SendActionResponseFromJson(json!); + static SendActionResponse fromJson(Map json) => + _$SendActionResponseFromJson(json); } /// Model response for [Channel.addMembers] api call @JsonSerializable(createToJson: false) class AddMembersResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members - List? members; + @JsonKey(defaultValue: []) + late List members; /// Message returned by the api call Message? message; /// Create a new instance from a json - static AddMembersResponse fromJson(Map? json) => - _$AddMembersResponseFromJson(json!); + static AddMembersResponse fromJson(Map json) => + _$AddMembersResponseFromJson(json); } /// Model response for [Channel.acceptInvite] api call @JsonSerializable(createToJson: false) class AcceptInviteResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members - List? members; + @JsonKey(defaultValue: []) + late List members; /// Message returned by the api call Message? message; /// Create a new instance from a json - static AcceptInviteResponse fromJson(Map? json) => - _$AcceptInviteResponseFromJson(json!); + static AcceptInviteResponse fromJson(Map json) => + _$AcceptInviteResponseFromJson(json); } /// Model response for [Channel.rejectInvite] api call @JsonSerializable(createToJson: false) class RejectInviteResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// Channel members - List? members; + @JsonKey(defaultValue: []) + late List members; /// Message returned by the api call Message? message; /// Create a new instance from a json - static RejectInviteResponse fromJson(Map? json) => - _$RejectInviteResponseFromJson(json!); + static RejectInviteResponse fromJson(Map json) => + _$RejectInviteResponseFromJson(json); } /// Model response for empty responses @JsonSerializable(createToJson: false) class EmptyResponse extends _BaseResponse { /// Create a new instance from a json - static EmptyResponse fromJson(Map? json) => - _$EmptyResponseFromJson(json!); + static EmptyResponse fromJson(Map json) => + _$EmptyResponseFromJson(json); } /// Model response for [Channel.query] api call @JsonSerializable(createToJson: false) class ChannelStateResponse extends _BaseResponse { /// Updated channel - ChannelModel? channel; + late ChannelModel channel; /// List of messages returned by the api call - List? messages; + @JsonKey(defaultValue: []) + late List messages; /// Channel members - List? members; + @JsonKey(defaultValue: []) + late List members; /// Number of users watching the channel - int? watcherCount; + @JsonKey(defaultValue: 0) + late int watcherCount; /// List of read states - List? read; + @JsonKey(defaultValue: []) + late List read; /// Create a new instance from a json static ChannelStateResponse fromJson(Map json) => diff --git a/packages/stream_chat/lib/src/api/responses.g.dart b/packages/stream_chat/lib/src/api/responses.g.dart index e1363d0c..2358593d 100644 --- a/packages/stream_chat/lib/src/api/responses.g.dart +++ b/packages/stream_chat/lib/src/api/responses.g.dart @@ -10,8 +10,9 @@ SyncResponse _$SyncResponseFromJson(Map json) { return SyncResponse() ..duration = json['duration'] as String? ..events = (json['events'] as List?) - ?.map((e) => Event.fromJson(e as Map)) - .toList(); + ?.map((e) => Event.fromJson(e as Map)) + .toList() ?? + []; } QueryChannelsResponse _$QueryChannelsResponseFromJson( @@ -19,33 +20,35 @@ QueryChannelsResponse _$QueryChannelsResponseFromJson( return QueryChannelsResponse() ..duration = json['duration'] as String? ..channels = (json['channels'] as List?) - ?.map((e) => ChannelState.fromJson(e as Map)) - .toList(); + ?.map((e) => ChannelState.fromJson(e as Map)) + .toList() ?? + []; } TranslateMessageResponse _$TranslateMessageResponseFromJson( Map json) { return TranslateMessageResponse() ..duration = json['duration'] as String? - ..message = json['message'] == null - ? null - : TranslatedMessage.fromJson(json['message'] as Map); + ..message = + TranslatedMessage.fromJson(json['message'] as Map); } QueryMembersResponse _$QueryMembersResponseFromJson(Map json) { return QueryMembersResponse() ..duration = json['duration'] as String? ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList(); + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + []; } QueryUsersResponse _$QueryUsersResponseFromJson(Map json) { return QueryUsersResponse() ..duration = json['duration'] as String? ..users = (json['users'] as List?) - ?.map((e) => User.fromJson(e as Map)) - .toList(); + ?.map((e) => User.fromJson(e as Map)) + .toList() ?? + []; } QueryReactionsResponse _$QueryReactionsResponseFromJson( @@ -53,90 +56,82 @@ QueryReactionsResponse _$QueryReactionsResponseFromJson( return QueryReactionsResponse() ..duration = json['duration'] as String? ..reactions = (json['reactions'] as List?) - ?.map((e) => Reaction.fromJson(e as Map)) - .toList(); + ?.map((e) => Reaction.fromJson(e as Map)) + .toList() ?? + []; } QueryRepliesResponse _$QueryRepliesResponseFromJson(Map json) { return QueryRepliesResponse() ..duration = json['duration'] as String? ..messages = (json['messages'] as List?) - ?.map((e) => Message.fromJson(e as Map)) - .toList(); + ?.map((e) => Message.fromJson(e as Map)) + .toList() ?? + []; } ListDevicesResponse _$ListDevicesResponseFromJson(Map json) { return ListDevicesResponse() ..duration = json['duration'] as String? ..devices = (json['devices'] as List?) - ?.map((e) => Device.fromJson(e as Map)) - .toList(); + ?.map((e) => Device.fromJson(e as Map)) + .toList() ?? + []; } SendFileResponse _$SendFileResponseFromJson(Map json) { return SendFileResponse() ..duration = json['duration'] as String? - ..file = json['file'] as String?; + ..file = json['file'] as String; } SendImageResponse _$SendImageResponseFromJson(Map json) { return SendImageResponse() ..duration = json['duration'] as String? - ..file = json['file'] as String?; + ..file = json['file'] as String; } SendReactionResponse _$SendReactionResponseFromJson(Map json) { return SendReactionResponse() ..duration = json['duration'] as String? - ..message = json['message'] == null - ? null - : Message.fromJson(json['message'] as Map) - ..reaction = json['reaction'] == null - ? null - : Reaction.fromJson(json['reaction'] as Map); + ..message = Message.fromJson(json['message'] as Map) + ..reaction = Reaction.fromJson(json['reaction'] as Map); } ConnectGuestUserResponse _$ConnectGuestUserResponseFromJson( Map json) { return ConnectGuestUserResponse() ..duration = json['duration'] as String? - ..accessToken = json['access_token'] as String? - ..user = json['user'] == null - ? null - : User.fromJson(json['user'] as Map); + ..accessToken = json['access_token'] as String + ..user = User.fromJson(json['user'] as Map); } UpdateUsersResponse _$UpdateUsersResponseFromJson(Map json) { return UpdateUsersResponse() ..duration = json['duration'] as String? ..users = (json['users'] as Map?)?.map( - (k, e) => MapEntry(k, User.fromJson(e as Map)), - ); + (k, e) => MapEntry(k, User.fromJson(e as Map)), + ) ?? + {}; } UpdateMessageResponse _$UpdateMessageResponseFromJson( Map json) { return UpdateMessageResponse() ..duration = json['duration'] as String? - ..message = json['message'] == null - ? null - : Message.fromJson(json['message'] as Map); + ..message = Message.fromJson(json['message'] as Map); } SendMessageResponse _$SendMessageResponseFromJson(Map json) { return SendMessageResponse() ..duration = json['duration'] as String? - ..message = json['message'] == null - ? null - : Message.fromJson(json['message'] as Map); + ..message = Message.fromJson(json['message'] as Map); } GetMessageResponse _$GetMessageResponseFromJson(Map json) { return GetMessageResponse() ..duration = json['duration'] as String? - ..message = json['message'] == null - ? null - : Message.fromJson(json['message'] as Map) + ..message = Message.fromJson(json['message'] as Map) ..channel = json['channel'] == null ? null : ChannelModel.fromJson(json['channel'] as Map); @@ -147,8 +142,9 @@ SearchMessagesResponse _$SearchMessagesResponseFromJson( return SearchMessagesResponse() ..duration = json['duration'] as String? ..results = (json['results'] as List?) - ?.map((e) => GetMessageResponse.fromJson(e as Map)) - .toList(); + ?.map((e) => GetMessageResponse.fromJson(e as Map)) + .toList() ?? + []; } GetMessagesByIdResponse _$GetMessagesByIdResponseFromJson( @@ -156,17 +152,16 @@ GetMessagesByIdResponse _$GetMessagesByIdResponseFromJson( return GetMessagesByIdResponse() ..duration = json['duration'] as String? ..messages = (json['messages'] as List?) - ?.map((e) => Message.fromJson(e as Map)) - .toList(); + ?.map((e) => Message.fromJson(e as Map)) + .toList() ?? + []; } UpdateChannelResponse _$UpdateChannelResponseFromJson( Map json) { return UpdateChannelResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) ?.map((e) => Member.fromJson(e as Map)) .toList() @@ -179,9 +174,7 @@ PartialUpdateChannelResponse _$PartialUpdateChannelResponseFromJson( Map json) { return PartialUpdateChannelResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) ?.map((e) => Member.fromJson(e as Map)) .toList(); @@ -191,12 +184,11 @@ InviteMembersResponse _$InviteMembersResponseFromJson( Map json) { return InviteMembersResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList() + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + [] ..message = json['message'] == null ? null : Message.fromJson(json['message'] as Map); @@ -206,12 +198,11 @@ RemoveMembersResponse _$RemoveMembersResponseFromJson( Map json) { return RemoveMembersResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList() + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + [] ..message = json['message'] == null ? null : Message.fromJson(json['message'] as Map); @@ -228,12 +219,11 @@ SendActionResponse _$SendActionResponseFromJson(Map json) { AddMembersResponse _$AddMembersResponseFromJson(Map json) { return AddMembersResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList() + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + [] ..message = json['message'] == null ? null : Message.fromJson(json['message'] as Map); @@ -242,12 +232,11 @@ AddMembersResponse _$AddMembersResponseFromJson(Map json) { AcceptInviteResponse _$AcceptInviteResponseFromJson(Map json) { return AcceptInviteResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList() + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + [] ..message = json['message'] == null ? null : Message.fromJson(json['message'] as Map); @@ -256,12 +245,11 @@ AcceptInviteResponse _$AcceptInviteResponseFromJson(Map json) { RejectInviteResponse _$RejectInviteResponseFromJson(Map json) { return RejectInviteResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList() + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + [] ..message = json['message'] == null ? null : Message.fromJson(json['message'] as Map); @@ -274,17 +262,18 @@ EmptyResponse _$EmptyResponseFromJson(Map json) { ChannelStateResponse _$ChannelStateResponseFromJson(Map json) { return ChannelStateResponse() ..duration = json['duration'] as String? - ..channel = json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map) + ..channel = ChannelModel.fromJson(json['channel'] as Map) ..messages = (json['messages'] as List?) - ?.map((e) => Message.fromJson(e as Map)) - .toList() + ?.map((e) => Message.fromJson(e as Map)) + .toList() ?? + [] ..members = (json['members'] as List?) - ?.map((e) => Member.fromJson(e as Map)) - .toList() - ..watcherCount = json['watcher_count'] as int? + ?.map((e) => Member.fromJson(e as Map)) + .toList() ?? + [] + ..watcherCount = json['watcher_count'] as int? ?? 0 ..read = (json['read'] as List?) - ?.map((e) => Read.fromJson(e as Map)) - .toList(); + ?.map((e) => Read.fromJson(e as Map)) + .toList() ?? + []; } diff --git a/packages/stream_chat/lib/src/attachment_file_uploader.dart b/packages/stream_chat/lib/src/attachment_file_uploader.dart index 70976d40..7b90f0c9 100644 --- a/packages/stream_chat/lib/src/attachment_file_uploader.dart +++ b/packages/stream_chat/lib/src/attachment_file_uploader.dart @@ -1,8 +1,8 @@ import 'package:dio/dio.dart'; import 'package:stream_chat/src/api/responses.dart'; import 'package:stream_chat/src/client.dart'; -import 'package:stream_chat/src/models/attachment_file.dart'; import 'package:stream_chat/src/extensions/string_extension.dart'; +import 'package:stream_chat/src/models/attachment_file.dart'; /// Class responsible for uploading images and files to a given channel abstract class AttachmentFileUploader { @@ -13,8 +13,8 @@ abstract class AttachmentFileUploader { /// and cancel the request using [cancelToken] Future sendImage( AttachmentFile image, - String? channelId, - String? channelType, { + String channelId, + String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, }); @@ -26,8 +26,8 @@ abstract class AttachmentFileUploader { /// and cancel the request using [cancelToken] Future sendFile( AttachmentFile file, - String? channelId, - String? channelType, { + String channelId, + String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, }); @@ -38,8 +38,8 @@ abstract class AttachmentFileUploader { /// Optionally, cancel the request using [cancelToken] Future deleteImage( String url, - String? channelId, - String? channelType, { + String channelId, + String channelType, { CancelToken? cancelToken, }); @@ -49,8 +49,8 @@ abstract class AttachmentFileUploader { /// Optionally, cancel the request using [cancelToken] Future deleteFile( String url, - String? channelId, - String? channelType, { + String channelId, + String channelType, { CancelToken? cancelToken, }); } @@ -65,8 +65,8 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { @override Future sendImage( AttachmentFile file, - String? channelId, - String? channelType, { + String channelId, + String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, }) async { @@ -102,8 +102,8 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { @override Future sendFile( AttachmentFile file, - String? channelId, - String? channelType, { + String channelId, + String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, }) async { @@ -139,8 +139,8 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { @override Future deleteImage( String url, - String? channelId, - String? channelType, { + String channelId, + String channelType, { CancelToken? cancelToken, }) async { final response = await _client.delete( @@ -154,8 +154,8 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { @override Future deleteFile( String url, - String? channelId, - String? channelType, { + String channelId, + String channelType, { CancelToken? cancelToken, }) async { final response = await _client.delete( diff --git a/packages/stream_chat/lib/src/client.dart b/packages/stream_chat/lib/src/client.dart index 46eb21af..fa007456 100644 --- a/packages/stream_chat/lib/src/client.dart +++ b/packages/stream_chat/lib/src/client.dart @@ -82,7 +82,7 @@ class StreamChatClient { this.tokenProvider, this.baseURL = _defaultBaseURL, this.logLevel = Level.WARNING, - this.logHandlerFunction, + LogHandlerFunction? logHandlerFunction, Duration connectTimeout = const Duration(seconds: 6), Duration receiveTimeout = const Duration(seconds: 6), Dio? httpClient, @@ -103,7 +103,7 @@ class StreamChatClient { state = ClientState(this); - _setupLogger(); + _setupLogger(logHandlerFunction); _setupDio(httpClient, receiveTimeout, connectTimeout); logger.info('instantiating new client'); @@ -134,7 +134,7 @@ class StreamChatClient { RetryPolicy? get retryPolicy => _retryPolicy; /// This client state - late final ClientState state; + late ClientState state; /// By default the Chat client will write all messages with level Warn or /// Error to stdout. @@ -170,7 +170,7 @@ class StreamChatClient { /// final client = StreamChatClient("stream-chat-api-key", /// logHandlerFunction: myLogHandlerFunction); ///``` - LogHandlerFunction? logHandlerFunction; + late LogHandlerFunction logHandlerFunction; /// Your project Stream Chat api key. /// Find your API keys here https://getstream.io/dashboard/ @@ -371,14 +371,14 @@ class StreamChatClient { ) => Logger.detached(name) ..level = logLevel - ..onRecord.listen(logHandlerFunction ?? _getDefaultLogHandler()); + ..onRecord.listen(logHandlerFunction); - void _setupLogger() { + void _setupLogger(LogHandlerFunction? logHandlerFunction) { logger.level = logLevel; - logHandlerFunction ??= _getDefaultLogHandler(); + this.logHandlerFunction = logHandlerFunction ?? _getDefaultLogHandler(); - logger.onRecord.listen(logHandlerFunction); + logger.onRecord.listen(this.logHandlerFunction); logger.info('logger setup'); } @@ -618,15 +618,15 @@ class StreamChatClient { SyncResponse.fromJson, ); - res.events!.sort((a, b) => a.createdAt!.compareTo(b.createdAt!)); + res.events.sort((a, b) => a.createdAt!.compareTo(b.createdAt!)); - res.events!.forEach((element) { + res.events.forEach((element) { logger ..fine('element.type: ${element.type}') ..fine('element.message.text: ${element.message?.text}'); }); - res.events!.forEach(handleEvent); + res.events.forEach(handleEvent); await _chatPersistenceClient?.updateLastSyncAt(DateTime.now()); _synced = true; @@ -740,7 +740,7 @@ class StreamChatClient { QueryChannelsResponse.fromJson, ); - if ((res.channels ?? []).isEmpty && paginationParams.offset == 0) { + if (res.channels.isEmpty && paginationParams.offset == 0) { logger.warning( ''' We could not find any channel for this query. @@ -750,7 +750,7 @@ class StreamChatClient { return []; } - final channels = res.channels!; + final channels = res.channels; final users = channels .expand((it) => it.members) @@ -759,7 +759,7 @@ class StreamChatClient { state._updateUsers(users); - logger.info('Got ${res.channels?.length} channels from api'); + logger.info('Got ${res.channels.length} channels from api'); final updateData = _mapChannelStateToChannel(channels); @@ -1053,7 +1053,7 @@ class StreamChatClient { QueryUsersResponse.fromJson, ); - state._updateUsers(response.users!); + state._updateUsers(response.users); return response; } @@ -1100,8 +1100,8 @@ class StreamChatClient { /// Send a [file] to the [channelId] of type [channelType] Future sendFile( AttachmentFile file, - String? channelId, - String? channelType, { + String channelId, + String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, }) => @@ -1116,8 +1116,8 @@ class StreamChatClient { /// Send a [image] to the [channelId] of type [channelType] Future sendImage( AttachmentFile image, - String? channelId, - String? channelType, { + String channelId, + String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, }) => @@ -1132,8 +1132,8 @@ class StreamChatClient { /// Delete a file from this channel Future deleteFile( String url, - String? channelId, - String? channelType, { + String channelId, + String channelType, { CancelToken? cancelToken, }) => attachmentFileUploader!.deleteFile( @@ -1146,8 +1146,8 @@ class StreamChatClient { /// Delete an image from this channel Future deleteImage( String url, - String? channelId, - String? channelType, { + String channelId, + String channelType, { CancelToken? cancelToken, }) => attachmentFileUploader!.deleteImage( @@ -1327,7 +1327,10 @@ class StreamChatClient { /// Sends the message to the given channel Future sendMessage( - Message message, String? channelId, String? channelType) async { + Message message, + String channelId, + String channelType, + ) async { final response = await post( '/channels/$channelType/$channelId/message', data: {'message': message.toJson()}, diff --git a/packages/stream_chat/lib/src/models/action.dart b/packages/stream_chat/lib/src/models/action.dart index b91f1e13..16a307e7 100644 --- a/packages/stream_chat/lib/src/models/action.dart +++ b/packages/stream_chat/lib/src/models/action.dart @@ -6,22 +6,29 @@ part 'action.g.dart'; @JsonSerializable() class Action { /// Constructor used for json serialization - Action({this.name, this.style, this.text, this.type, this.value}); + Action({ + required this.name, + this.style = 'default', + required this.text, + required this.type, + this.value, + }); /// Create a new instance from a json factory Action.fromJson(Map json) => _$ActionFromJson(json); /// The name of the action - final String? name; + final String name; /// The style of the action - final String? style; + @JsonKey(defaultValue: 'default') + final String style; /// The test of the action - final String? text; + final String text; /// The type of the action - final String? type; + final String type; /// The value of the action final String? value; diff --git a/packages/stream_chat/lib/src/models/action.g.dart b/packages/stream_chat/lib/src/models/action.g.dart index 770298c7..9ae999ed 100644 --- a/packages/stream_chat/lib/src/models/action.g.dart +++ b/packages/stream_chat/lib/src/models/action.g.dart @@ -8,10 +8,10 @@ part of 'action.dart'; Action _$ActionFromJson(Map json) { return Action( - name: json['name'] as String?, - style: json['style'] as String?, - text: json['text'] as String?, - type: json['type'] as String?, + name: json['name'] as String, + style: json['style'] as String? ?? 'default', + text: json['text'] as String, + type: json['type'] as String, value: json['value'] as String?, ); } diff --git a/packages/stream_chat/lib/src/models/attachment.dart b/packages/stream_chat/lib/src/models/attachment.dart index 877c292d..fd91454a 100644 --- a/packages/stream_chat/lib/src/models/attachment.dart +++ b/packages/stream_chat/lib/src/models/attachment.dart @@ -15,7 +15,7 @@ class Attachment extends Equatable { /// Constructor used for json serialization Attachment({ String? id, - String? type, + this.type, this.titleLink, String? title, this.thumbUrl, @@ -32,14 +32,14 @@ class Attachment extends Equatable { this.authorLink, this.authorIcon, this.assetUrl, - this.actions, + List? actions, this.extraData, this.file, UploadState? uploadState, }) : id = id ?? const Uuid().v4(), title = title ?? file?.name, - type = type ?? '', - localUri = file?.path != null ? Uri.parse(file!.path!) : null { + localUri = file?.path != null ? Uri.parse(file!.path!) : null, + actions = actions ?? [] { this.uploadState = uploadState ?? ((assetUrl != null || imageUrl != null) ? const UploadState.success() @@ -58,7 +58,7 @@ class Attachment extends Equatable { ///The attachment type based on the URL resource. This can be: audio, ///image or video - final String type; + final String? type; ///The link to which the attachment message points to. final String? titleLink; @@ -98,7 +98,8 @@ class Attachment extends Equatable { final String? assetUrl; /// Actions from a command - final List? actions; + @JsonKey(defaultValue: []) + final List actions; final Uri? localUri; @@ -106,7 +107,7 @@ class Attachment extends Equatable { final AttachmentFile? file; /// The current upload state of the attachment - late final UploadState? uploadState; + late final UploadState uploadState; /// Map of custom channel extraData @JsonKey(includeIfNull: false) @@ -149,13 +150,13 @@ class Attachment extends Equatable { ]; /// Serialize to json - Map toJson() => Serialization.moveFromExtraDataToRoot( - _$AttachmentToJson(this), topLevelFields) - ..removeWhere((key, value) => dbSpecificTopLevelFields.contains(key)); + Map toJson() => + Serialization.moveFromExtraDataToRoot(_$AttachmentToJson(this)) + ..removeWhere((key, value) => dbSpecificTopLevelFields.contains(key)); /// Serialize to db data - Map toData() => Serialization.moveFromExtraDataToRoot( - _$AttachmentToJson(this), topLevelFields + dbSpecificTopLevelFields); + Map toData() => + Serialization.moveFromExtraDataToRoot(_$AttachmentToJson(this)); Attachment copyWith({ String? id, diff --git a/packages/stream_chat/lib/src/models/attachment.g.dart b/packages/stream_chat/lib/src/models/attachment.g.dart index acee04fa..b7a7304d 100644 --- a/packages/stream_chat/lib/src/models/attachment.g.dart +++ b/packages/stream_chat/lib/src/models/attachment.g.dart @@ -27,8 +27,9 @@ Attachment _$AttachmentFromJson(Map json) { authorIcon: json['author_icon'] as String?, assetUrl: json['asset_url'] as String?, actions: (json['actions'] as List?) - ?.map((e) => Action.fromJson(e as Map)) - .toList(), + ?.map((e) => Action.fromJson(e as Map)) + .toList() ?? + [], extraData: json['extra_data'] as Map?, file: json['file'] == null ? null @@ -40,9 +41,7 @@ Attachment _$AttachmentFromJson(Map json) { } Map _$AttachmentToJson(Attachment instance) { - final val = { - 'type': instance.type, - }; + final val = {}; void writeNotNull(String key, dynamic value) { if (value != null) { @@ -50,6 +49,7 @@ Map _$AttachmentToJson(Attachment instance) { } } + writeNotNull('type', instance.type); writeNotNull('title_link', instance.titleLink); writeNotNull('title', instance.title); writeNotNull('thumb_url', instance.thumbUrl); @@ -66,9 +66,9 @@ Map _$AttachmentToJson(Attachment instance) { writeNotNull('author_link', instance.authorLink); writeNotNull('author_icon', instance.authorIcon); writeNotNull('asset_url', instance.assetUrl); - writeNotNull('actions', instance.actions?.map((e) => e.toJson()).toList()); + val['actions'] = instance.actions.map((e) => e.toJson()).toList(); writeNotNull('file', instance.file?.toJson()); - writeNotNull('upload_state', instance.uploadState?.toJson()); + val['upload_state'] = instance.uploadState.toJson(); writeNotNull('extra_data', instance.extraData); val['id'] = instance.id; return val; diff --git a/packages/stream_chat/lib/src/models/attachment_file.dart b/packages/stream_chat/lib/src/models/attachment_file.dart index fa74d801..d72cecbd 100644 --- a/packages/stream_chat/lib/src/models/attachment_file.dart +++ b/packages/stream_chat/lib/src/models/attachment_file.dart @@ -4,7 +4,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:meta/meta.dart'; part 'attachment_file.freezed.dart'; - part 'attachment_file.g.dart'; /// Union class to hold various [UploadState] of a attachment. @@ -14,8 +13,10 @@ class UploadState with _$UploadState { const factory UploadState.preparing() = Preparing; /// InProgress state of the union - const factory UploadState.inProgress( - {required int uploaded, required int total}) = InProgress; + const factory UploadState.inProgress({ + required int uploaded, + required int total, + }) = InProgress; /// Success state of the union const factory UploadState.success() = Success; @@ -62,7 +63,10 @@ class AttachmentFile { this.name, this.bytes, this.size, - }); + }) : assert( + path != null || bytes != null, + 'Either path or bytes should be != null', + ); /// Create a new instance from a json factory AttachmentFile.fromJson(Map json) => diff --git a/packages/stream_chat/lib/src/models/channel_config.dart b/packages/stream_chat/lib/src/models/channel_config.dart index 1500aaf2..9ba36e4f 100644 --- a/packages/stream_chat/lib/src/models/channel_config.dart +++ b/packages/stream_chat/lib/src/models/channel_config.dart @@ -1,5 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:stream_chat/src/models/command.dart'; + part 'channel_config.g.dart'; /// The class that contains the information about the configuration of a channel @@ -7,75 +8,85 @@ part 'channel_config.g.dart'; class ChannelConfig { /// Constructor used for json serialization ChannelConfig({ - this.automod, - this.commands, - this.connectEvents, - this.createdAt, - this.updatedAt, - this.maxMessageLength, - this.messageRetention, - this.mutes, - this.name, - this.reactions, - this.readEvents, - this.replies, - this.search, - this.typingEvents, - this.uploads, - this.urlEnrichment, - }); + this.automod = 'flag', + this.commands = const [], + this.connectEvents = false, + DateTime? createdAt, + DateTime? updatedAt, + this.maxMessageLength = 0, + this.messageRetention = '', + this.mutes = false, + this.reactions = false, + this.readEvents = false, + this.replies = false, + this.search = false, + this.typingEvents = false, + this.uploads = false, + this.urlEnrichment = false, + }) : createdAt = createdAt ?? DateTime.now(), + updatedAt = updatedAt ?? DateTime.now(); /// Create a new instance from a json factory ChannelConfig.fromJson(Map json) => _$ChannelConfigFromJson(json); /// Moderation configuration - final String? automod; + @JsonKey(defaultValue: 'flag') + final String automod; /// List of available commands - final List? commands; + @JsonKey(defaultValue: []) + final List commands; /// True if the channel should send connect events - final bool? connectEvents; + @JsonKey(defaultValue: false) + final bool connectEvents; /// Date of channel creation - final DateTime? createdAt; + final DateTime createdAt; /// Date of last channel update - final DateTime? updatedAt; + final DateTime updatedAt; /// Max channel message length - final int? maxMessageLength; + @JsonKey(defaultValue: 0) + final int maxMessageLength; /// Duration of message retention - final String? messageRetention; + @JsonKey(defaultValue: '') + final String messageRetention; /// True if users can be muted - final bool? mutes; - - /// Name of the channel - final String? name; + @JsonKey(defaultValue: false) + final bool mutes; /// True if reaction are active for this channel - final bool? reactions; + @JsonKey(defaultValue: false) + final bool reactions; /// True if readEvents are active for this channel - final bool? readEvents; + @JsonKey(defaultValue: false) + final bool readEvents; /// True if reply message are active for this channel - final bool? replies; + @JsonKey(defaultValue: false) + final bool replies; /// True if it's possible to perform a search in this channel - final bool? search; + @JsonKey(defaultValue: false) + final bool search; /// True if typing events should be sent for this channel - final bool? typingEvents; + @JsonKey(defaultValue: false) + final bool typingEvents; /// True if it's possible to upload files to this channel - final bool? uploads; + @JsonKey(defaultValue: false) + final bool uploads; /// True if urls appears as attachments - final bool? urlEnrichment; + @JsonKey(defaultValue: false) + final bool urlEnrichment; /// Serialize to json Map toJson() => _$ChannelConfigToJson(this); diff --git a/packages/stream_chat/lib/src/models/channel_config.g.dart b/packages/stream_chat/lib/src/models/channel_config.g.dart index 41cd0cd2..723281c0 100644 --- a/packages/stream_chat/lib/src/models/channel_config.g.dart +++ b/packages/stream_chat/lib/src/models/channel_config.g.dart @@ -8,42 +8,41 @@ part of 'channel_config.dart'; ChannelConfig _$ChannelConfigFromJson(Map json) { return ChannelConfig( - automod: json['automod'] as String?, + automod: json['automod'] as String? ?? 'flag', commands: (json['commands'] as List?) - ?.map((e) => Command.fromJson(e as Map)) - .toList(), - connectEvents: json['connect_events'] as bool?, + ?.map((e) => Command.fromJson(e as Map)) + .toList() ?? + [], + connectEvents: json['connect_events'] as bool? ?? false, createdAt: json['created_at'] == null ? null : DateTime.parse(json['created_at'] as String), updatedAt: json['updated_at'] == null ? null : DateTime.parse(json['updated_at'] as String), - maxMessageLength: json['max_message_length'] as int?, - messageRetention: json['message_retention'] as String?, - mutes: json['mutes'] as bool?, - name: json['name'] as String?, - reactions: json['reactions'] as bool?, - readEvents: json['read_events'] as bool?, - replies: json['replies'] as bool?, - search: json['search'] as bool?, - typingEvents: json['typing_events'] as bool?, - uploads: json['uploads'] as bool?, - urlEnrichment: json['url_enrichment'] as bool?, + maxMessageLength: json['max_message_length'] as int? ?? 0, + messageRetention: json['message_retention'] as String? ?? '', + mutes: json['mutes'] as bool? ?? false, + reactions: json['reactions'] as bool? ?? false, + readEvents: json['read_events'] as bool? ?? false, + replies: json['replies'] as bool? ?? false, + search: json['search'] as bool? ?? false, + typingEvents: json['typing_events'] as bool? ?? false, + uploads: json['uploads'] as bool? ?? false, + urlEnrichment: json['url_enrichment'] as bool? ?? false, ); } Map _$ChannelConfigToJson(ChannelConfig instance) => { 'automod': instance.automod, - 'commands': instance.commands?.map((e) => e.toJson()).toList(), + 'commands': instance.commands.map((e) => e.toJson()).toList(), 'connect_events': instance.connectEvents, - 'created_at': instance.createdAt?.toIso8601String(), - 'updated_at': instance.updatedAt?.toIso8601String(), + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), 'max_message_length': instance.maxMessageLength, 'message_retention': instance.messageRetention, 'mutes': instance.mutes, - 'name': instance.name, 'reactions': instance.reactions, 'read_events': instance.readEvents, 'replies': instance.replies, diff --git a/packages/stream_chat/lib/src/models/channel_model.dart b/packages/stream_chat/lib/src/models/channel_model.dart index edd373ae..d68edbde 100644 --- a/packages/stream_chat/lib/src/models/channel_model.dart +++ b/packages/stream_chat/lib/src/models/channel_model.dart @@ -10,9 +10,9 @@ part 'channel_model.g.dart'; class ChannelModel { /// Constructor used for json serialization ChannelModel({ - this.id, - this.type, - this.cid = '', + String? id, + String? type, + String? cid, ChannelConfig? config, this.createdBy, this.frozen = false, @@ -25,7 +25,14 @@ class ChannelModel { this.team, }) : config = config ?? ChannelConfig(), createdAt = createdAt ?? DateTime.now(), - updatedAt = updatedAt ?? DateTime.now(); + updatedAt = updatedAt ?? DateTime.now(), + assert( + cid != null || (id != null && type != null), + 'provide either a cid or an id and type', + ), + id = id ?? cid!.split(':')[1], + type = type ?? cid!.split(':')[0], + cid = cid ?? '$type:$id'; /// Create a new instance from a json factory ChannelModel.fromJson(Map json) => @@ -33,10 +40,10 @@ class ChannelModel { Serialization.moveToExtraDataFromRoot(json, topLevelFields)); /// The id of this channel - final String? id; + final String id; /// The type of this channel - final String? type; + final String type; /// The cid of this channel @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) @@ -107,7 +114,6 @@ class ChannelModel { /// Serialize to json Map toJson() => Serialization.moveFromExtraDataToRoot( _$ChannelModelToJson(this), - topLevelFields, ); /// Creates a copy of [ChannelModel] with specified attributes overridden. diff --git a/packages/stream_chat/lib/src/models/channel_model.g.dart b/packages/stream_chat/lib/src/models/channel_model.g.dart index 58a9b61e..e71112b6 100644 --- a/packages/stream_chat/lib/src/models/channel_model.g.dart +++ b/packages/stream_chat/lib/src/models/channel_model.g.dart @@ -10,7 +10,7 @@ ChannelModel _$ChannelModelFromJson(Map json) { return ChannelModel( id: json['id'] as String?, type: json['type'] as String?, - cid: json['cid'] as String, + cid: json['cid'] as String?, config: json['config'] == null ? null : ChannelConfig.fromJson(json['config'] as Map), diff --git a/packages/stream_chat/lib/src/models/command.dart b/packages/stream_chat/lib/src/models/command.dart index c8df72fd..5ba0043c 100644 --- a/packages/stream_chat/lib/src/models/command.dart +++ b/packages/stream_chat/lib/src/models/command.dart @@ -7,9 +7,9 @@ part 'command.g.dart'; class Command { /// Constructor used for json serialization Command({ - this.name, - this.description, - this.args, + required this.name, + required this.description, + required this.args, }); /// Create a new instance from a json @@ -17,13 +17,13 @@ class Command { _$CommandFromJson(json); /// The name of the command - final String? name; + final String name; /// The description explaining the command - final String? description; + final String description; /// The arguments of the command - final String? args; + final String args; /// Serialize to json Map toJson() => _$CommandToJson(this); diff --git a/packages/stream_chat/lib/src/models/command.g.dart b/packages/stream_chat/lib/src/models/command.g.dart index 1ce00415..cf8be971 100644 --- a/packages/stream_chat/lib/src/models/command.g.dart +++ b/packages/stream_chat/lib/src/models/command.g.dart @@ -8,9 +8,9 @@ part of 'command.dart'; Command _$CommandFromJson(Map json) { return Command( - name: json['name'] as String?, - description: json['description'] as String?, - args: json['args'] as String?, + name: json['name'] as String, + description: json['description'] as String, + args: json['args'] as String, ); } diff --git a/packages/stream_chat/lib/src/models/device.dart b/packages/stream_chat/lib/src/models/device.dart index 24dcb678..5dc98d25 100644 --- a/packages/stream_chat/lib/src/models/device.dart +++ b/packages/stream_chat/lib/src/models/device.dart @@ -7,8 +7,8 @@ part 'device.g.dart'; class Device { /// Constructor used for json serialization Device({ - this.id = '', - this.pushProvider, + required this.id, + required this.pushProvider, }); /// Create a new instance from a json @@ -18,7 +18,7 @@ class Device { final String id; /// The notification push provider - final String? pushProvider; + final String pushProvider; /// Serialize to json Map toJson() => _$DeviceToJson(this); diff --git a/packages/stream_chat/lib/src/models/device.g.dart b/packages/stream_chat/lib/src/models/device.g.dart index fe65053b..5fcd9435 100644 --- a/packages/stream_chat/lib/src/models/device.g.dart +++ b/packages/stream_chat/lib/src/models/device.g.dart @@ -9,7 +9,7 @@ part of 'device.dart'; Device _$DeviceFromJson(Map json) { return Device( id: json['id'] as String, - pushProvider: json['push_provider'] as String?, + pushProvider: json['push_provider'] as String, ); } diff --git a/packages/stream_chat/lib/src/models/event.dart b/packages/stream_chat/lib/src/models/event.dart index 621464b6..52092656 100644 --- a/packages/stream_chat/lib/src/models/event.dart +++ b/packages/stream_chat/lib/src/models/event.dart @@ -119,7 +119,6 @@ class Event { /// Serialize to json Map toJson() => Serialization.moveFromExtraDataToRoot( _$EventToJson(this), - topLevelFields, ); /// Creates a copy of [Event] with specified attributes overridden. @@ -217,6 +216,5 @@ class EventChannel extends ChannelModel { @override Map toJson() => Serialization.moveFromExtraDataToRoot( _$EventChannelToJson(this), - topLevelFields, ); } diff --git a/packages/stream_chat/lib/src/models/member.dart b/packages/stream_chat/lib/src/models/member.dart index ad5f64c8..49df170c 100644 --- a/packages/stream_chat/lib/src/models/member.dart +++ b/packages/stream_chat/lib/src/models/member.dart @@ -13,9 +13,9 @@ class Member { this.inviteAcceptedAt, this.inviteRejectedAt, this.invited = false, - this.role = '', + this.role, this.userId, - this.isModerator, + this.isModerator = false, DateTime? createdAt, DateTime? updatedAt, this.banned = false, @@ -45,14 +45,14 @@ class Member { final bool invited; /// The role of the user in the channel - @JsonKey(defaultValue: '') - final String role; + final String? role; /// The id of the interested user final String? userId; /// True if the user is a moderator of the channel - final bool? isModerator; + @JsonKey(defaultValue: false) + final bool isModerator; /// True if the member is banned from the channel @JsonKey(defaultValue: false) diff --git a/packages/stream_chat/lib/src/models/member.g.dart b/packages/stream_chat/lib/src/models/member.g.dart index 091cb109..a75b458d 100644 --- a/packages/stream_chat/lib/src/models/member.g.dart +++ b/packages/stream_chat/lib/src/models/member.g.dart @@ -18,9 +18,9 @@ Member _$MemberFromJson(Map json) { ? null : DateTime.parse(json['invite_rejected_at'] as String), invited: json['invited'] as bool? ?? false, - role: json['role'] as String? ?? '', + role: json['role'] as String?, userId: json['user_id'] as String?, - isModerator: json['is_moderator'] as bool?, + isModerator: json['is_moderator'] as bool? ?? false, createdAt: json['created_at'] == null ? null : DateTime.parse(json['created_at'] as String), diff --git a/packages/stream_chat/lib/src/models/message.dart b/packages/stream_chat/lib/src/models/message.dart index b25662c0..03a162c5 100644 --- a/packages/stream_chat/lib/src/models/message.dart +++ b/packages/stream_chat/lib/src/models/message.dart @@ -46,12 +46,12 @@ class Message extends Equatable { /// Constructor used for json serialization Message({ String? id, - this.text = '', - this.type = '', - this.attachments, - this.mentionedUsers, - this.silent, - this.shadowed, + this.text, + this.type = 'regular', + this.attachments = const [], + this.mentionedUsers = const [], + this.silent = false, + this.shadowed = false, this.reactionCounts, this.reactionScores, this.latestReactions, @@ -70,10 +70,10 @@ class Message extends Equatable { this.pinnedAt, DateTime? pinExpires, this.pinnedBy, - this.extraData, + this.extraData = const {}, this.deletedAt, this.status = MessageSendingStatus.sent, - this.skipPush, + this.skipPush = false, }) : id = id ?? const Uuid().v4(), pinExpires = pinExpires?.toUtc(), createdAt = createdAt ?? DateTime.now(), @@ -88,24 +88,34 @@ class Message extends Equatable { final String id; /// The text of this message - final String text; + final String? text; /// The status of a sending message @JsonKey(ignore: true) final MessageSendingStatus status; /// The message type - @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) + @JsonKey( + includeIfNull: false, + toJson: Serialization.readOnly, + defaultValue: 'regular', + ) final String type; /// The list of attachments, either provided by the user or generated from a /// command or as a result of URL scraping. - @JsonKey(includeIfNull: false) - final List? attachments; + @JsonKey( + includeIfNull: false, + defaultValue: [], + ) + final List attachments; /// The list of user mentioned in the message - @JsonKey(toJson: Serialization.userIds) - final List? mentionedUsers; + @JsonKey( + toJson: Serialization.userIds, + defaultValue: [], + ) + final List mentionedUsers; /// A map describing the count of number of every reaction @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) @@ -145,14 +155,20 @@ class Message extends Equatable { final bool? showInChannel; /// If true the message is silent - final bool? silent; + @JsonKey(defaultValue: false) + final bool silent; /// If true the message will not send a push notification - final bool? skipPush; + @JsonKey(defaultValue: false) + final bool skipPush; /// If true the message is shadowed - @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) - final bool? shadowed; + @JsonKey( + includeIfNull: false, + toJson: Serialization.readOnly, + defaultValue: false, + ) + final bool shadowed; /// A used command name. @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) @@ -171,7 +187,8 @@ class Message extends Equatable { final User? user; /// If true the message is pinned - final bool? pinned; + @JsonKey(defaultValue: false) + final bool pinned; /// Reserved field indicating when the message was pinned @JsonKey(toJson: Serialization.readOnly) @@ -187,8 +204,11 @@ class Message extends Equatable { final User? pinnedBy; /// Message custom extraData - @JsonKey(includeIfNull: false) - final Map? extraData; + @JsonKey( + includeIfNull: false, + defaultValue: {}, + ) + final Map extraData; /// True if the message is a system info bool get isSystem => type == 'system'; @@ -238,7 +258,8 @@ class Message extends Equatable { /// Serialize to json Map toJson() => Serialization.moveFromExtraDataToRoot( - _$MessageToJson(this), topLevelFields); + _$MessageToJson(this), + ); /// Creates a copy of [Message] with specified attributes overridden. Message copyWith({ @@ -408,6 +429,5 @@ class TranslatedMessage extends Message { @override Map toJson() => Serialization.moveFromExtraDataToRoot( _$TranslatedMessageToJson(this), - topLevelFields, ); } diff --git a/packages/stream_chat/lib/src/models/message.g.dart b/packages/stream_chat/lib/src/models/message.g.dart index 9dfea3c4..ca094a83 100644 --- a/packages/stream_chat/lib/src/models/message.g.dart +++ b/packages/stream_chat/lib/src/models/message.g.dart @@ -9,16 +9,18 @@ part of 'message.dart'; Message _$MessageFromJson(Map json) { return Message( id: json['id'] as String?, - text: json['text'] as String, - type: json['type'] as String, + text: json['text'] as String?, + type: json['type'] as String? ?? 'regular', attachments: (json['attachments'] as List?) - ?.map((e) => Attachment.fromJson(e as Map)) - .toList(), + ?.map((e) => Attachment.fromJson(e as Map)) + .toList() ?? + [], mentionedUsers: (json['mentioned_users'] as List?) - ?.map((e) => User.fromJson(e as Map)) - .toList(), - silent: json['silent'] as bool?, - shadowed: json['shadowed'] as bool?, + ?.map((e) => User.fromJson(e as Map)) + .toList() ?? + [], + silent: json['silent'] as bool? ?? false, + shadowed: json['shadowed'] as bool? ?? false, reactionCounts: (json['reaction_counts'] as Map?)?.map( (k, e) => MapEntry(k, e as int), ), @@ -51,7 +53,7 @@ Message _$MessageFromJson(Map json) { user: json['user'] == null ? null : User.fromJson(json['user'] as Map), - pinned: json['pinned'] as bool?, + pinned: json['pinned'] as bool? ?? false, pinnedAt: json['pinned_at'] == null ? null : DateTime.parse(json['pinned_at'] as String), @@ -61,11 +63,11 @@ Message _$MessageFromJson(Map json) { pinnedBy: json['pinned_by'] == null ? null : User.fromJson(json['pinned_by'] as Map), - extraData: json['extra_data'] as Map?, + extraData: json['extra_data'] as Map? ?? {}, deletedAt: json['deleted_at'] == null ? null : DateTime.parse(json['deleted_at'] as String), - skipPush: json['skip_push'] as bool?, + skipPush: json['skip_push'] as bool? ?? false, ); } @@ -82,8 +84,7 @@ Map _$MessageToJson(Message instance) { } writeNotNull('type', readonly(instance.type)); - writeNotNull( - 'attachments', instance.attachments?.map((e) => e.toJson()).toList()); + val['attachments'] = instance.attachments.map((e) => e.toJson()).toList(); val['mentioned_users'] = Serialization.userIds(instance.mentionedUsers); writeNotNull('reaction_counts', readonly(instance.reactionCounts)); writeNotNull('reaction_scores', readonly(instance.reactionScores)); @@ -106,7 +107,7 @@ Map _$MessageToJson(Message instance) { val['pinned_at'] = readonly(instance.pinnedAt); val['pin_expires'] = instance.pinExpires?.toIso8601String(); val['pinned_by'] = readonly(instance.pinnedBy); - writeNotNull('extra_data', instance.extraData); + val['extra_data'] = instance.extraData; writeNotNull('deleted_at', readonly(instance.deletedAt)); return val; } diff --git a/packages/stream_chat/lib/src/models/mute.dart b/packages/stream_chat/lib/src/models/mute.dart index 65300d4a..3ba26230 100644 --- a/packages/stream_chat/lib/src/models/mute.dart +++ b/packages/stream_chat/lib/src/models/mute.dart @@ -9,26 +9,31 @@ part 'mute.g.dart'; @JsonSerializable() class Mute { /// Constructor used for json serialization - Mute({this.user, this.channel, this.createdAt, this.updatedAt}); + Mute({ + required this.user, + required this.channel, + required this.createdAt, + required this.updatedAt, + }); /// Create a new instance from a json factory Mute.fromJson(Map json) => _$MuteFromJson(json); /// The user that performed the muting action @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) - final User? user; + final User user; /// The target user @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) - final ChannelModel? channel; + final ChannelModel channel; /// The date in which the use was muted @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) - final DateTime? createdAt; + final DateTime createdAt; /// The date of the last update @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) - final DateTime? updatedAt; + final DateTime updatedAt; /// Serialize to json Map toJson() => _$MuteToJson(this); diff --git a/packages/stream_chat/lib/src/models/mute.g.dart b/packages/stream_chat/lib/src/models/mute.g.dart index 652a1bc3..e77b8707 100644 --- a/packages/stream_chat/lib/src/models/mute.g.dart +++ b/packages/stream_chat/lib/src/models/mute.g.dart @@ -8,18 +8,10 @@ part of 'mute.dart'; Mute _$MuteFromJson(Map json) { return Mute( - user: json['user'] == null - ? null - : User.fromJson(json['user'] as Map), - channel: json['channel'] == null - ? null - : ChannelModel.fromJson(json['channel'] as Map), - createdAt: json['created_at'] == null - ? null - : DateTime.parse(json['created_at'] as String), - updatedAt: json['updated_at'] == null - ? null - : DateTime.parse(json['updated_at'] as String), + user: User.fromJson(json['user'] as Map), + channel: ChannelModel.fromJson(json['channel'] as Map), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), ); } diff --git a/packages/stream_chat/lib/src/models/own_user.dart b/packages/stream_chat/lib/src/models/own_user.dart index d22f706e..3ce951cf 100644 --- a/packages/stream_chat/lib/src/models/own_user.dart +++ b/packages/stream_chat/lib/src/models/own_user.dart @@ -84,5 +84,6 @@ class OwnUser extends User { /// Serialize to json @override Map toJson() => Serialization.moveFromExtraDataToRoot( - _$OwnUserToJson(this), topLevelFields); + _$OwnUserToJson(this), + ); } diff --git a/packages/stream_chat/lib/src/models/reaction.dart b/packages/stream_chat/lib/src/models/reaction.dart index 767f1057..eefeaebe 100644 --- a/packages/stream_chat/lib/src/models/reaction.dart +++ b/packages/stream_chat/lib/src/models/reaction.dart @@ -11,7 +11,7 @@ class Reaction { Reaction({ this.messageId, DateTime? createdAt, - this.type = '', + required this.type, required this.user, String? userId, this.score = 0, @@ -64,7 +64,8 @@ class Reaction { /// Serialize to json Map toJson() => Serialization.moveFromExtraDataToRoot( - _$ReactionToJson(this), topLevelFields); + _$ReactionToJson(this), + ); /// Creates a copy of [Reaction] with specified attributes overridden. Reaction copyWith({ diff --git a/packages/stream_chat/lib/src/models/read.dart b/packages/stream_chat/lib/src/models/read.dart index ef20eb6e..cbd47dd1 100644 --- a/packages/stream_chat/lib/src/models/read.dart +++ b/packages/stream_chat/lib/src/models/read.dart @@ -10,7 +10,7 @@ class Read { Read({ required this.lastRead, required this.user, - required this.unreadMessages, + this.unreadMessages = 0, }); /// Create a new instance from a json diff --git a/packages/stream_chat/lib/src/models/serialization.dart b/packages/stream_chat/lib/src/models/serialization.dart index 6cd4cfbd..d584912e 100644 --- a/packages/stream_chat/lib/src/models/serialization.dart +++ b/packages/stream_chat/lib/src/models/serialization.dart @@ -10,7 +10,7 @@ class Serialization { static const Function readOnly = readonly; /// List of users to list of userIds - static List? userIds(List? users) => + static List? userIds(List? users) => users?.map((u) => u.id).toList(); /// Takes unknown json keys and puts them in the `extra_data` key @@ -36,7 +36,6 @@ class Serialization { /// the json map static Map moveFromExtraDataToRoot( Map json, - List topLevelFields, ) { final jsonClone = Map.from(json); return jsonClone diff --git a/packages/stream_chat/lib/src/models/user.dart b/packages/stream_chat/lib/src/models/user.dart index 224e0f20..67fc99f0 100644 --- a/packages/stream_chat/lib/src/models/user.dart +++ b/packages/stream_chat/lib/src/models/user.dart @@ -105,8 +105,9 @@ class User { other is User && runtimeType == other.runtimeType && id == other.id; /// Serialize to json - Map toJson() => - Serialization.moveFromExtraDataToRoot(_$UserToJson(this), topLevelFields); + Map toJson() => Serialization.moveFromExtraDataToRoot( + _$UserToJson(this), + ); /// Creates a copy of [User] with specified attributes overridden. User copyWith({ diff --git a/packages/stream_chat/test/src/api/channel_test.dart b/packages/stream_chat/test/src/api/channel_test.dart index 4717f524..e0a29cc8 100644 --- a/packages/stream_chat/test/src/api/channel_test.dart +++ b/packages/stream_chat/test/src/api/channel_test.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:dio/dio.dart'; import 'package:dio/native_imp.dart'; import 'package:mocktail/mocktail.dart'; @@ -6,11 +8,10 @@ import 'package:stream_chat/src/client.dart'; import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/models/event.dart'; import 'package:stream_chat/src/models/message.dart'; -import 'package:stream_chat/src/models/reaction.dart'; import 'package:stream_chat/src/models/own_user.dart'; -import 'package:test/test.dart'; - +import 'package:stream_chat/src/models/reaction.dart'; import 'package:stream_chat/stream_chat.dart'; +import 'package:test/test.dart'; class MockDio extends Mock implements DioForNative {} @@ -76,7 +77,7 @@ void main() { any(), data: any(named: 'data'), )).thenAnswer((_) async => Response( - data: '{}', + data: jsonEncode(ChannelState()), statusCode: 200, requestOptions: FakeRequestOptions(), )); diff --git a/packages/stream_chat/test/src/client_test.dart b/packages/stream_chat/test/src/client_test.dart index 4e880bed..c93059d5 100644 --- a/packages/stream_chat/test/src/client_test.dart +++ b/packages/stream_chat/test/src/client_test.dart @@ -9,9 +9,9 @@ import 'package:mocktail/mocktail.dart'; import 'package:stream_chat/src/api/requests.dart'; import 'package:stream_chat/src/client.dart'; import 'package:stream_chat/src/exceptions.dart'; +import 'package:stream_chat/src/models/channel_model.dart'; import 'package:stream_chat/src/models/message.dart'; import 'package:stream_chat/src/models/user.dart'; -import 'package:stream_chat/src/models/channel_model.dart'; import 'package:test/test.dart'; class MockDio extends Mock implements DioForNative {} @@ -748,7 +748,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': message}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -793,7 +793,7 @@ void main() { when(() => mockDio.get('/messages/$messageId')).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': Message(id: messageId)}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -1115,7 +1115,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': message}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -1137,7 +1137,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'message': message}), statusCode: 200, requestOptions: FakeRequestOptions(), ), @@ -1177,7 +1177,7 @@ void main() { ), ).thenAnswer( (_) async => Response( - data: '{}', + data: jsonEncode({'channel': ChannelModel(cid: 'messaging:test')}), statusCode: 200, requestOptions: FakeRequestOptions(), ), diff --git a/packages/stream_chat/test/src/models/attachment_test.dart b/packages/stream_chat/test/src/models/attachment_test.dart index 1ca45132..1342e72e 100644 --- a/packages/stream_chat/test/src/models/attachment_test.dart +++ b/packages/stream_chat/test/src/models/attachment_test.dart @@ -1,7 +1,7 @@ import 'dart:convert'; -import 'package:stream_chat/src/models/attachment.dart'; -import 'package:stream_chat/src/models/action.dart'; +import 'package:stream_chat/src/models/action.dart'; +import 'package:stream_chat/src/models/attachment.dart'; import 'package:test/test.dart'; void main() { @@ -50,7 +50,7 @@ void main() { 'https://media0.giphy.com/media/3o7TKnCdBx5cMg0qti/giphy.gif', ); expect(attachment.actions, hasLength(3)); - expect(attachment.actions![0], isA()); + expect(attachment.actions[0], isA()); }); test('should serialize to json correctly', () { @@ -67,7 +67,8 @@ void main() { 'type': 'image', 'title': 'soo', 'title_link': - 'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti' + 'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti', + 'actions': [], }, ); }); diff --git a/packages/stream_chat/test/src/models/channel_state_test.dart b/packages/stream_chat/test/src/models/channel_state_test.dart index 98d08596..afe384f5 100644 --- a/packages/stream_chat/test/src/models/channel_state_test.dart +++ b/packages/stream_chat/test/src/models/channel_state_test.dart @@ -1,12 +1,12 @@ import 'dart:convert'; -import 'package:test/test.dart'; import 'package:stream_chat/src/models/channel_config.dart'; import 'package:stream_chat/src/models/channel_state.dart'; import 'package:stream_chat/src/models/command.dart'; import 'package:stream_chat/src/models/message.dart'; import 'package:stream_chat/src/models/user.dart'; import 'package:stream_chat/stream_chat.dart'; +import 'package:test/test.dart'; void main() { group('src/models/channel_state', () { @@ -852,7 +852,7 @@ void main() { expect(channelState.channel?.config, isA()); expect(channelState.channel?.config, isNotNull); expect(channelState.channel?.config.commands, hasLength(1)); - expect(channelState.channel?.config.commands![0], isA()); + expect(channelState.channel?.config.commands[0], isA()); expect(channelState.channel?.lastMessageAt, DateTime.parse('2020-01-30T13:43:41.062362Z')); expect(channelState.channel?.createdAt, @@ -902,7 +902,7 @@ void main() { "show_in_channel": null, "mentioned_users": [], "status": "SENT", - "skip_push": null, + "skip_push": false, "silent": false, "pinned": false, "pinned_at": null, @@ -919,7 +919,7 @@ void main() { "show_in_channel": null, "mentioned_users": [], "status": "SENT", - "skip_push": null, + "skip_push": false, "silent": false, "pinned": false, "pinned_at": null, @@ -929,7 +929,7 @@ void main() { { "id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0", "text": "test message", - "skip_push": null, + "skip_push": false, "attachments": [], "parent_id": null, "quoted_message": null, @@ -952,7 +952,7 @@ void main() { "quoted_message_id": null, "show_in_channel": null, "mentioned_users": [], - "skip_push": null, + "skip_push": false, "status": "SENT", "silent": false, "pinned": false, @@ -964,7 +964,7 @@ void main() { "id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe", "text": "test", "attachments": [], - "skip_push": null, + "skip_push": false, "parent_id": null, "quoted_message": null, "quoted_message_id": null, @@ -982,7 +982,7 @@ void main() { "text": "hi", "attachments": [], "parent_id": null, - "skip_push": null, + "skip_push": false, "quoted_message": null, "quoted_message_id": null, "show_in_channel": null, @@ -1000,7 +1000,7 @@ void main() { "attachments": [], "parent_id": null, "quoted_message": null, - "skip_push": null, + "skip_push": false, "quoted_message_id": null, "show_in_channel": null, "mentioned_users": [], @@ -1023,7 +1023,7 @@ void main() { "status": "SENT", "silent": false, "pinned": false, - "skip_push": null, + "skip_push": false, "pinned_at": null, "pin_expires": null, "pinned_by": null @@ -1041,7 +1041,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1053,7 +1053,7 @@ void main() { "quoted_message": null, "quoted_message_id": null, "show_in_channel": null, - "skip_push": null, + "skip_push": false, "mentioned_users": [], "status": "SENT", "silent": false, @@ -1071,7 +1071,7 @@ void main() { "quoted_message_id": null, "show_in_channel": null, "mentioned_users": [], - "skip_push": null, + "skip_push": false, "status": "SENT", "silent": false, "pinned": false, @@ -1090,7 +1090,7 @@ void main() { "mentioned_users": [], "status": "SENT", "silent": false, - "skip_push": null, + "skip_push": false, "pinned": false, "pinned_at": null, "pin_expires": null, @@ -1100,7 +1100,7 @@ void main() { "id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055", "text": "what are you doing?", "attachments": [], - "skip_push": null, + "skip_push": false, "parent_id": null, "quoted_message": null, "quoted_message_id": null, @@ -1118,7 +1118,7 @@ void main() { "text": "👍", "attachments": [], "parent_id": null, - "skip_push": null, + "skip_push": false, "quoted_message": null, "quoted_message_id": null, "show_in_channel": null, @@ -1134,7 +1134,7 @@ void main() { "id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21", "text": "sdasas", "attachments": [], - "skip_push": null, + "skip_push": false, "parent_id": null, "quoted_message": null, "quoted_message_id": null, @@ -1155,7 +1155,7 @@ void main() { "quoted_message": null, "quoted_message_id": null, "show_in_channel": null, - "skip_push": null, + "skip_push": false, "mentioned_users": [], "status": "SENT", "silent": false, @@ -1168,7 +1168,7 @@ void main() { "id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d", "text": "nhisagdhsadz", "attachments": [], - "skip_push": null, + "skip_push": false, "parent_id": null, "quoted_message": null, "quoted_message_id": null, @@ -1187,7 +1187,7 @@ void main() { "attachments": [], "parent_id": null, "quoted_message": null, - "skip_push": null, + "skip_push": false, "quoted_message_id": null, "show_in_channel": null, "mentioned_users": [], @@ -1204,7 +1204,7 @@ void main() { "attachments": [], "parent_id": null, "quoted_message": null, - "skip_push": null, + "skip_push": false, "quoted_message_id": null, "show_in_channel": null, "mentioned_users": [], @@ -1212,7 +1212,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1229,7 +1229,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1246,7 +1246,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1263,7 +1263,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1280,7 +1280,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1297,7 +1297,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null }, @@ -1314,7 +1314,7 @@ void main() { "silent": false, "pinned": false, "pinned_at": null, - "skip_push": null, + "skip_push": false, "pin_expires": null, "pinned_by": null } diff --git a/packages/stream_chat/test/src/models/channel_test.dart b/packages/stream_chat/test/src/models/channel_test.dart index a48c5a23..01c06fee 100644 --- a/packages/stream_chat/test/src/models/channel_test.dart +++ b/packages/stream_chat/test/src/models/channel_test.dart @@ -1,7 +1,7 @@ import 'dart:convert'; -import 'package:test/test.dart'; import 'package:stream_chat/src/models/channel_model.dart'; +import 'package:test/test.dart'; void main() { group('src/models/channel', () { @@ -9,7 +9,7 @@ void main() { { "id": "test", "type": "livestream", - "cid": "test:livestream", + "cid": "livestream:test", "cats": true, "fruit": ["bananas", "apples"] } @@ -19,7 +19,7 @@ void main() { final channel = ChannelModel.fromJson(json.decode(jsonExample)); expect(channel.id, equals('test')); expect(channel.type, equals('livestream')); - expect(channel.cid, equals('test:livestream')); + expect(channel.cid, equals('livestream:test')); expect(channel.extraData!['cats'], equals(true)); expect(channel.extraData!['fruit'], equals(['bananas', 'apples'])); }); diff --git a/packages/stream_chat/test/src/models/message_test.dart b/packages/stream_chat/test/src/models/message_test.dart index a34911cf..ddaed93f 100644 --- a/packages/stream_chat/test/src/models/message_test.dart +++ b/packages/stream_chat/test/src/models/message_test.dart @@ -1,10 +1,10 @@ import 'dart:convert'; -import 'package:test/test.dart'; import 'package:stream_chat/src/models/attachment.dart'; import 'package:stream_chat/src/models/message.dart'; import 'package:stream_chat/src/models/reaction.dart'; import 'package:stream_chat/src/models/user.dart'; +import 'package:test/test.dart'; void main() { group('src/models/message', () { @@ -134,7 +134,7 @@ void main() { "id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f", "text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA", "silent": false, - "skip_push": null, + "skip_push": false, "attachments": [ { "type": "video", @@ -145,10 +145,11 @@ void main() { "og_scrape_url": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA", "image_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif", "author_name": "GIPHY", - "asset_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4" + "asset_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4", + "actions": [] } ], - "mentioned_users": null, + "mentioned_users": [], "parent_id": "parentId", "quoted_message": null, "quoted_message_id": null, diff --git a/packages/stream_chat_flutter/test/src/message_reactions_modal_test.dart b/packages/stream_chat_flutter/test/src/message_reactions_modal_test.dart index 044eb693..8745cb45 100644 --- a/packages/stream_chat_flutter/test/src/message_reactions_modal_test.dart +++ b/packages/stream_chat_flutter/test/src/message_reactions_modal_test.dart @@ -90,6 +90,7 @@ void main() { Reaction( messageId: 'test', user: User(id: 'testid'), + type: 'test', ), ], );